Управление системой / видимой областью отсечения в Windows 1809 - PullRequest
0 голосов
/ 07 февраля 2019

Очевидно, что Microsoft изменила способ работы отсечения с обновлением Windows 1809, выпущенным в конце 2018. До этого обновления GetClipBox() возвращало полный клиентский прямоугольник окна, даже если оно было (частично) за кадром.После обновления та же функция возвращает обрезанный прямоугольник, содержащий только те части, которые все еще находятся на экране. Это приводит к тому, что содержимое контекста устройства не обновляется для внеэкранной области, что не позволяет мне делать снимки экрана из этих окон.

Вопрос заключается в следующем: можно ли каким-то образом манипулировать областью отсечения?

Я немного исследовал, и кажется, что на конечную область отсечения влияют область окна, прямоугольник обновления и область системы - насколько я понимаю, «глобальная область отсечения».Я проверил область окна с помощью GetWindowRgn() и GetRgnBox(), оба возвращают одинаковые значения для Windows 1809 и более старых версий.GetUpdateRect() также возвращает полный прямоугольник клиента, так что это также не может быть проблемой.Я также пытался подключить метод BeginPaint() и посмотреть, что изменение PAINTSTRUCT.rcPaint что-то делает, безуспешно.

Итак, у меня остается попытка настроить системную область, или иногда ее называют видимойобласть, край.Тем не менее, я понятия не имею, если и как это возможно. MSDN предполагает, что это не , но я подумал, может быть, у кого-то есть идея для решения!?

РЕДАКТИРОВАТЬ: Чтобы сделать это более ясным, я недумаю, что отсечение выполняется самим приложением, потому что закадровые снимки экрана той же версии приложения работают до Windows 1809 и не работают с обновленной версией Windows.Вместо этого сама Windows, кажется, обрезает любые поверхности за пределами экрана.

EDIT2: Вот минимальный пример рабочего кода для создания снимка экрана.

// Get the client size.
RECT crect;
GetClientRect(hwnd, &crect);
int width = crect.right - crect.left;
int height = crect.bottom - crect.top;

// Create DC and Bitmap.
HDC windowDC = GetDC(hwnd);
HDC memoryDC = CreateCompatibleDC(windowDC);
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;
char* pixels;
HBITMAP bitmap = CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, (void**)&pixels, 0, 0);
HGDIOBJ previousObject = SelectObject(memoryDC, bitmap);

// Take the screenshot. Neither BitBlt nor PrintWindow work.
BitBlt(memoryDC, 0, 0, width, height, windowDC, 0, 0, SRCCOPY);
// ..or..
// PrintWindow(hwnd, memoryDC, PW_CLIENTONLY);

// Save the image.
BITMAPFILEHEADER bitmapFileHeader;
bitmapFileHeader.bfType = 0x4D42;
bitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
std::fstream hFile("./screenshot.bmp", std::ios::out | std::ios::binary);
if(hFile.is_open())
{
  hFile.write((char*)&bitmapFileHeader, sizeof(bitmapFileHeader));
  hFile.write((char*)&bitmapInfo.bmiHeader, sizeof(bitmapInfo.bmiHeader));
  hFile.write(pixels, (((32 * width + 31) & ~31) / 8) * height);
  hFile.close();
}

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

Вы можете загрузить скомпилированный исполняемый файл с Google Drive здесь .Используется Screenshot.exe <HWND>, где HWND - шестнадцатеричный адрес дескриптора окна, как это показано в Spy ++, например.Он сохранит снимок экрана с целевым окном в рабочем каталоге как screenshot.bmp (убедитесь, что вам разрешено писать в каталог).Снимок экрана будет работать почти для всех окон (даже если они скрыты за другими окнами), но как только вы частично переместите окно за пределы экрана, снимок экрана продолжит показывать содержимое старого окна за его пределами (изменить его размер)в то время как это за кадром, например, чтобы увидеть эффект).Это происходит только в Windows 1809, в более ранних версиях Windows все равно отображается обновленное содержимое.

...