Страница 1 из 1

Снимок окна оп его Handle

Добавлено: 05 Сентябрь 2010, 17:41
seawolf
Приветствую сообщество!
Возникал тема получить BMP из текущего окна (Handle понятно дело известен) путем собственного кода без всяких ImageEx . Изучен пример Grabber - если окно свернуто или на него положено другое то не получить его BMP корректно.

За основу пример из Delphi.

____________-
hSrcWnd := FindWindow(nil, PChAR('Test')); // "*********" - имя нужного окна
GetWindowRect(hSrcWnd, rcSrc);

Это опускаем так как эти параметры известны
hSrcWnd - хэндл окна

hDC1:= GetDC(hSrcWnd);
hSrcDC:=CreateCompatibleDC(hDC1);
hBmp := CreateCompatibleBitmap(hDC1, rcSrc.right - rcSrc.left, rcSrc.bottom - rcSrc.top);

SelectObject(hSrcDC, hBmp);
PrintWindow(hSrcWnd, hSrcDC, 0);

BitBlt(
hDC1,
0,
0,
rcSrc.right - rcSrc.left,
rcSrc.bottom - rcSrc.top,
hSrcDC,
0,
0,
SRCCOPY);

Здесь сохранение в файл

DeleteObject(hBmp);
DeleteDC(hSrcDC);
ReleaseDC(hSrcWnd, hDC1);
___________

У нас это примерно так с учетом примера Grabber

hDC1 = GetDC(hSrcWnd)
hdcCompatible = CreateCompatibleDC(hDC1)
hbmScreen = CreateCompatibleBitmap(hDC1,Rec.Right,Rec.Bottom)
IF NOT hbmScreen

RETURN 1
END

IF NOT SelectObject(hdcCompatible, hbmScreen)

RETURN 1
END

PrintWindow(hSrcWnd, hdcCompatible, 0)


IF NOT BitBlt(hDC1,0,0,Rec.Right,Rec.Bottom,hdcCompatible,Rec.Left,Rec.Top,SRCCOPY)

RETURN 1
END

Далее все освобождаем!


Собственно вопрос:
Проблема в объявлении PrintWindow никак не линкуется (в user32.dll точно есть такая функция )
PrintWindow(HWND, HDC, DWORD),BOOL,PASCAL,PROC или прототип не верен?

Re: Снимок окна оп его Handle

Добавлено: 05 Сентябрь 2010, 21:09
Дед Пахом
А LIB-файл с этой функцией в проект включён? В стандартных либах её нет.

Re: Снимок окна оп его Handle

Добавлено: 06 Сентябрь 2010, 2:23
WadimZapara
Или вариант: найти адрес этой функции и использовать по назначению:

Код: Выделить всё

PrintWindow ULONG,Static,Name('MePrintWindow')
   MAP
      MODULE ('')
         PrintWindow (UnSigned, UnSigned, ULong), BOOL, PASCAL, PROC, Name('MePrintWindow')
      END
      MODULE ('Windows.dll')
         LoadLibrary(*CString NameLibrary), UnSigned,RAW,Pascal,DLL(TRUE),Name('LoadLibraryA')
         GetProcAddress(UnSigned handle, *CString NameFunction), ULong,Raw,Pascal,DLL(TRUE)
         FreeLibrary(UnSigned handle),BOOL, RAW,Pascal,DLL(TRUE)
      END
   END
hLib unsigned
cs    CString('User32.dll<0>{50}')
   CODE
      ! Загрузка User32.dll
      hLib = LoadLibrary(cs);
      IF ~hLib Then MESSAGE('Не найдена User32.dll')
      ELSE
         ! Получение адреса функции PrintWindow
         cs = 'PrintWindow'
         PrintWindow = GetProcAddress(hLib, cs)
         If ~PrintWindow Then MESSAGE('В User32.dll не найдена функция PrintWindow').
      END
      IF PrintWindow THEN
! ЗДЕСЬ ИСПОЛЬЗУЕШЬ СВОЙ ТЕКСТ
! . . .
! ЗАВЕРШАЕШЬ ТАК (чисто хороший тон освобождать более ненужные ресурсы):
        FreeLibrary(hLib)
      END
      RETURN
MSDN грит, что не во всех операционках есть эта самая функция (Minimum supported client - Windows XP).
Поэтому предложенный вариант с небольшими изменениями (диагностикой) будет работать везде.

А если прилинковать либу с объявлением - будет работать в той среде, где скомпилил, и более новых ОС,
а на стареньких тачках с Windows 98/NT/2000 - приложение просто не запустится, обругав, что не найдена функция в библиотеке.

Re: Снимок окна оп его Handle

Добавлено: 06 Сентябрь 2010, 15:06
seawolf
Наивно полагал что это функция API посему lib не подключал. В Win 98 ее нет. При таком раскладе подгрузка через LoadLibrary оптимальна.
Использование GetWindowDC привело к тому что теперь скринится именно заданное по хэндлу окно а не весь десктоп. При этом работает без PrintWindow. Использование PrintWindow приводит к вылету сразу причина пока не ясна. Насколько я понял именно эта функция может дать скрин окна если оно будет свернуто. Без нее имеем просто черный скрин, посему ушел в google.

hDC1 = GetWindowDC(hSrcWnd)
hdcCompatible = CreateCompatibleDC(hDC1)
hbmScreen = CreateCompatibleBitmap(hDC1,recright, recbottom)
RetObject = SelectObject(hdcCompatible, hbmScreen)
PrintWindow(hSrcWnd, hdcCompatible, 0)

Re: Снимок окна оп его Handle

Добавлено: 09 Сентябрь 2010, 12:51
Yufil
Если окно развёрнуто, можно получить его положение по GetWindowRect и грабберу передать именно этот прямоугольник.
При необходимости временно развернуть окно и вытащить его на передний план несложно.
Всё вроде работает, но у меня на сграбленной картинке содержатся закрытые к настоящему моменту окна :( .
После танцев с бубном остался вариант с открытием (и сразу же закрытием) окошка 1x1 пиксел в сторонке, тогда грабится правильно