BitBlt для скрытого, свернутого или просто закрытого другим окна

Тема в разделе "WASM.WIN32", создана пользователем Xerx, 6 июл 2007.

  1. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    Суть в чем: если я вызову
    Код (Text):
    1. invoke StretchBlt, ebx, 0, 0, 100, 100, eax, 0, 0, 300, 300, SRCCOPY
    где
    Код (Text):
    1. invoke GetDC, 0
    2. mov ebx, eax
    а eax - HWND некоего окна (как получен - не важно), то получу нужный результат только в том случае, если исходное окно АКТИВНО (т.е. видно). В ином случае я получу просто область рабочего стола (другие окна), в которой находится невидимое сейчас исходное окно.
    Получилось очень сумбурно, но надеюсь вы поймете.

    Так вот, как получить содержимое окна в этом случае?
    P.S. Не надо предлагать SetForeground()+перерисовать+BitBlt+как-нить_убрать_обратно :derisive:

    Заранее спасибо!
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    Xerx
    Можно попробовать послать окну WM_PAINT/WM_PRINT/WM_PRINTCIENT, передав в wParam свой HDC.
     
  3. S_Alex

    S_Alex Alex

    Публикаций:
    0
    Регистрация:
    27 авг 2004
    Сообщения:
    561
    Адрес:
    Ukraine
    Юзай ВИРТУАЛЬНОЕ ОКНО (контекст памяти).
    Я уже приводил пример. Поищи в WASM рулит.
     
  4. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    q_q
    А поподробнее? Не совсем понимаю как это может помочь :dntknw:
    ....
    Попробовал конструкции вида
    Код (Text):
    1. hWnd = FindWindow("Notepad", NULL);
    2. hDC = GetDC(hWnd);
    3. SendMessage(hWnd, WM_PRINT, hDC, PRF_NONCLIENT || PRF_CLIENT || PRF_OWNED);
    4. ReleaseDC(hWnd, hDC);
    для всех трех сообщений. И ничего...

    S_Alex
    Хе! А зачем мне это? Мне нужно получать ВСЮ область окна (включая NC: заголовок, рамку и т.д. и т.п). Причем окна не моего, а совершенно произвольного. А контекст в памяти - это двойная буферизация.
     
  5. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Xerx
    Вообще-то имелось в виду, что контекст устройства свой выбираться будет, а не ноутпада. А так у Вас получается, что он сам себя обновляет. Я решил тоже попробовать, но видно руки кривые, так что срабатывает только для своих собственных контролов получить изображение. А чужие рисовать в моем контексте отказываются.
    Зато всё прекрасно получилось с помощью функции PrintWindow. Надеюсь поможет.
     
  6. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    l_inc
    Ой, точно. Опечатался. Переносил с asm'а и не то напечатал. У меня такой тестовый код:
    Код (Text):
    1. hWnd = FindWindow("Notepad", NULL); // просто пример. вообще должно работать для любого hWnd
    2. hDC = GetDC(0);
    3. SendMessage(hWnd, WM_PRINT, hDC, PRF_NONCLIENT || PRF_CLIENT || PRF_OWNED); // заодно WM_PAINT
    4. ReleaseDC(0, hDC);
    Блокнот был 1) свернут и 2) выставлен в top most. Никакого эффекта.

    И насчет PrintWindow. Хорошая штука. Так что предыдущий код отпадает - больше не зачем, вроде бы как.
    Одна проблема - если исходное окно свернуто, то отрисовывается только заголовок. Это вполне логично, но мне нужно получать содержимое окна ВСЕГДА. Как можно наименьшим количеством телодвижений и тем более визуальных изменений на экране (желательно вообще без них) корректно сделать окно не минимизированным? А то что-то не получилось корректно это сделать через [S|G]etWindowLong() и ShowWindow(). Получалось весьма страшно :derisive: (пример в аттаче)
     
  7. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    ShowWindow(SW_RESTORE)?
     
  8. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Xerx
    Можно еще попробовать GetWindowPlacement/SetWindowPlacement, но вряд ли эффект будет другим. Да и мелькание окна видно будет хоть c ShowWindow, хоть с SetWindowPlacement.
    P.S. По картинке можно подумать, что у вас выставлен в Windows эффект развертывание/затемнение. Если его убрать, то вроде изображение окна должно получаться нормальным. На SetWindowPlacement, в отличие от ShowWindow, этот эффект не влияет.
     
  9. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    IceStudent
    Нет, не настолько все просто :derisive: Не работает.

    l_inc
    Этот эффект я выключаю сразу при первом запуске свежей системы :derisive: Что-то еще... Да и что это за программа будет, если она некорректно будет работать при включенном этом стиле...

    P.S. Завтра (понедельник, 9 число) попаду на работу и набросаю пример на MASM, в котором только это и реализую. И выложу здесь. Может это чем поможет...
     
  10. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    Это типа аналог дублирования бэкслешей?? или простая очепятка?
     
  11. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    asmfan
    Опечатка конечно :derisive:
     
  12. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    asmfan; Xerx
    А в чём опечатка-то?
    Xerx
    Код (Text):
    1. hDC = GetDC(0);
    И всё-таки я думаю, что имелся в виду по настоящему свой hDC. Хотя порисовать на рабочем столе - тоже неплохая идея.
     
  13. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    l_inc
    А в чём опечатка-то?
    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3.  
    4. void main(void)
    5. {
    6.   printf("0x%08X\n", PRF_NONCLIENT || PRF_CLIENT || PRF_OWNED);
    7.   printf("0x%08X\n", PRF_NONCLIENT | PRF_CLIENT | PRF_OWNED);
    8. }
    9.  
    10. Вывод
    11. 0x00000001
    12. 0x00000026
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    q_q
    Мда-а. Мозгов мне раньше не хватило додуматься, причём здесь бэкслэши. :)
    Спасибо за разъяснение.
     
  15. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    l_inc
    Нет, на сей раз все правильно :derisive: Это же тестовый код! Если нарисует на рабочем столе, то нарисует где угодно (в пределах допустимого, конечно).
     
  16. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    Вот в принципе рабочий код. Только что плохо - при восстановлении (SendMessage(... SW_RESTORE)) и последующем сворачивании окно мерцает. Это понятно. Но может есть способ лучше для получения "снимка" окна?

    Код (Text):
    1. .386
    2. .model flat, stdcall
    3. option casemap:none
    4.  
    5. include windows.inc
    6. include kernel32.inc
    7. include user32.inc
    8.  
    9. includelib kernel32.lib
    10. includelib user32.lib
    11.  
    12. .data
    13.     szNotepad       db 'Notepad',0
    14.     szU32Lib        db 'user32.dll',0
    15.     szPrintWindow   db 'PrintWindow',0
    16.    
    17. .data?
    18.     hU32Lib         dd ?
    19.     fPrintWindow    dd ?
    20.     bWasMinimize    dd  ?
    21.  
    22. .code
    23.  
    24. start:
    25. ; Инициализация
    26.     invoke  LoadLibrary, addr szU32Lib
    27.     mov     hU32Lib,    eax
    28.     invoke  GetProcAddress, eax, addr szPrintWindow
    29.     mov     fPrintWindow,   eax
    30.  
    31.     push    ebx
    32.    
    33.     invoke  FindWindow, addr szNotepad, NULL
    34.     mov     ebx,    eax
    35.  
    36. ; Тест на свернутое окно
    37.     invoke  GetWindowLong, ebx, GWL_STYLE
    38.     and     eax,    WS_MINIMIZE
    39.     mov     bWasMinimize,   eax
    40.     jz      @F
    41.         invoke  ShowWindow, ebx, SW_RESTORE
    42.     @@:
    43.  
    44. ; Непосредственно получение копии окна
    45.     invoke  GetDC, 0
    46.     push    eax
    47.    
    48.     ; invoke PrintWindow, ebx, eax, 0
    49.     push    0
    50.     push    eax
    51.     push    ebx
    52.     call    fPrintWindow
    53.    
    54.     pop     eax
    55.     invoke  ReleaseDC, 0, eax
    56.    
    57. ; Если окно было свернуто - сворачиваю обратно
    58.     mov     eax,    bWasMinimize
    59.     test    eax,    eax
    60.     jz      @F
    61.         invoke  ShowWindow, ebx, SW_MINIMIZE
    62.     @@:
    63.    
    64. ; Заметаю следы
    65.     pop     ebx
    66.    
    67.     invoke  FreeLibrary, hU32Lib
    68.     invoke  ExitProcess, 0
    69. end start
    Вариант с
    Код (Text):
    1.     invoke  GetWindowLong, ebx, GWL_STYLE
    2.         and     eax,    not WS_MINIMIZE
    3.         invoke  SetWindowLong, ebx, GWL_STYLE, eax
    не прошел.
     
  17. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    И что, неужели никому нечего на это ответить? Не верю.
     
  18. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Xerx
    Интересно, может проще перенести окно на другой десктоп и не мучаться с минимизацией/разворачиванием?
     
  19. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    IceStudent
    Это как?
     
  20. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Xerx
    Мысль была ошибочна, т.к. документированная работа с десктопами и "станциями окон" только из текущего процесса/потока. Да и, наверное, при переключении окна на другой десктоп будет такой же эффект, что и с минимизированным окном.