Joh*_*ker 25 c++ windows winapi clipping
显然,微软已经改变了2018年末发布的Windows更新1809的剪辑方式.在更新之前,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);
Run Code Online (Sandbox Code Playgroud)
你可以下载一个从谷歌这里开车编译成可执行文件.用法是Screenshot.exe <HWND>,其中HWND是窗口句柄的十六进制地址,例如在Spy ++中显示.它会将目标窗口的屏幕截图保存在工作目录中screenshot.bmp(确保允许您写入目录).屏幕截图几乎适用于所有窗口(即使它们隐藏在其他窗口后面),但只要您将窗口部分移动到屏幕外,屏幕截图就会继续显示窗口屏幕外部分的旧窗口内容(调整窗口大小)虽然它在屏幕外,例如,看到效果).这只发生在Windows 1809上,它仍然显示早期Windows版本的最新内容.