PrintWindow и BitBlt скрытых окон - PullRequest
0 голосов
/ 10 декабря 2018

Моя программа делает скриншоты других окон приложений, чтобы автоматизировать некоторые задачи на них.Эти окна могут время от времени скрываться за кадром или скрываться другими окнами.

Чтобы уменьшить беспорядок, я удалил любую проверку ошибок из списков кода.Я готовлю скриншоты обоих типов с

// Get size of the target window.
RECT clientRect;
GetClientRect(hwnd, &clientRect);
int width = clientRect.right - clientRect.left;
int height = clientRect.bottom - clientRect.top;
// Create a memory device context.
HDC windowDC = GetDC(hwnd);
HDC memoryDC = CreateCompatibleDC(windowDC);
// Create a bitmap for rendering.
BITMAPINFO bitmapInfo;
ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = -height;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biSizeImage = width * height * 4;
RGBQUAD* buffer;
HBITMAP bitmap = CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, 0, 0);
HGDIOBJ previousObject = SelectOBject(memoryDC, bitmap);

, затем снимаю скриншоты либо с

PrintWindow(hwnd, memoryDC, PW_CLIENTONLY); 
GdiFlush();

, либо с

UpdateWindow(hwnd);
BitBlt(memoryDC, 0, 0, width, height, windowDC, 0, 0, SRCCOPY);
GdiFlush();

, затем копируюсодержимое буфера для вектора

std::vector<RGBQUAD> pixels;
pixels.resize(width * height, { 0, 0, 0, 0 });
memcpy(&pixels[0], buffer, bitmapInfo.bmiHeader.biSizeImage);

и, наконец, я все очищаю с помощью

ReleaseDC(hwnd, windowDC);
SelectObject(memoryDC, previousObject);
DeleteDC(memoryDC);
DeleteObject(bitmap);

У меня есть три вопроса по поводу кода выше:

  1. Мне нужно позвонить GdiFlush()?Я прочитал документацию и провел некоторые исследования в Google, но я все еще не уверен, имеет ли смысл звонить или нет.
  2. Имеет ли смысл звонок на UpdateWindow() прямо перед BitBlt()?Помогает ли это, чтобы содержимое контекста устройства было «более современным»?
  3. Прав ли я, предполагая, что для PrintWindow() вся работа выполняется из целевого приложения (увеличение ЦП целевого приложения)использование), в то время как BitBlt() полностью выполняется из вызывающего потока (таким образом увеличивая использование ЦП моего собственного приложения)?
  4. При каких обстоятельствах может произойти сбой любой из вышеперечисленных функций?Я знаю, что BitBlt() работает только для скрытых окон, если включена Композиция рабочего стола (DWM), но в очень небольшом наборе систем (Windows 8/10) BitBlt() и PrintWindow() не работают для окон, для которых они работают.просто отлично в других системах (хотя DWM включен).Хотя я не смог найти никаких примеров того, почему.

Любая информация приветствуется, спасибо.

Ответы [ 2 ]

0 голосов
/ 19 апреля 2019

наконец, после нескольких часов исследования, я нашел решение для этой проблемы: достаточно вызвать следующую команду в событии ACTIVATE формы, которую нужно отобразить (пример в VB-кодировании):

Call SetWindowLong(me.hwnd, GWL_EXSTYLE, WS_EX_LAYERED)

Принимая во внимание, что эта команда определена следующим образом:

Private Declare Function SetWindowLong Lib "User32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Const GWL_EXSTYLE = (-20)

Private Const WS_EX_LAYERED = &H80000

Пожалуйста, попробуйте это!

С уважением, Bambi66

0 голосов
/ 07 февраля 2019

Спустя более двух месяцев я наконец понял, что это происходит только с обновлением Windows 1809 от конца 2018. Очевидно, Windows изменила способ обработки клиппирования с этим обновлением, так что содержимое контекста устройства больше не обновляется для частей оконкоторые находятся за кадром.

Чтобы ответить на отдельные вопросы:

1) GdiFlush, похоже, не имеет значения, по крайней мере, из того, что я могу сказать до сих пор.

2) Все еще не уверен на 100%, но я также думаю, что это не имеет значения.

3) Все еще не знаю.

4) См. Ответ выше.

...