【发布时间】:2018-05-16 22:02:42
【问题描述】:
我正在尝试每隔几秒定期比较同一窗口的快照。即使从技术上讲窗口没有改变,图片保持不变,我仍然会收到通知图片中的某些内容发生了变化,我正在使用旧的BitBlt 函数来捕获特定的窗口。和Zlib's CRC32 比较结果。
这是 2 张相同图片的示例,唯一的区别是窗口的标题 (untitled paint) 颜色。只要窗口有焦点,它就是黑色的,否则是灰色的。由于我不是 HWND 的所有者,有没有比更改样式更好的方法来拍照而不计算窗口的实际大小减去 GetSystemMetrices(SM_CYSIZEFRAME / SM_CXSIZE)。
我的代码:
WINDOWPLACEMENT rect;
::GetWindowPlacement(windowDesc.hWnd, &rect);
if (SW_SHOWMINIMIZED == rect.showCmd)
{
return;
}
CImage img;
img.Create(
rect.rcNormalPosition.right - rect.rcNormalPosition.left,
rect.rcNormalPosition.bottom - rect.rcNormalPosition.top,
32);
HWND hWnd = windowDesc.hWnd;
std::shared_ptr<HDC__> spSrcHdc(::GetDC(hWnd), [hWnd](HDC hdc) {::ReleaseDC(hWnd, hdc); });
//::BitBlt(img.GetDC(), 0, 0, img.GetWidth(), img.GetHeight(), spSrcHdc.get(), 0, 0, SRCCOPY);
::PrintWindow(hWnd, img.GetDC(), 0x2);
BITMAP bmp = { 0 };
if (!::GetObject((HBITMAP)img, sizeof(BITMAP), &bmp))
{
throw std::exception("Failed to retrieve raw bmp buffer");
}
unsigned long ulbmpCRC = crc32(0,
(BYTE*)bmp.bmBits, bmp.bmWidthBytes * bmp.bmHeight);
if (0 != ulbmpCRC && ulbmpCRC == windowDesc.crc)
{
}
我未能解决的另一个问题是文本框出现时。事实上,我的光标闪烁,它会生成不同的 CRC32 值。再一次,我可以使用具有忽略这种现象的能力的 BitBlt 吗?
【问题讨论】:
-
没有通用的方法来做你想做的事。主题 UI 的系统度量值是错误的,您也不能简单地要求客户矩形,因为某些应用程序(如 Visual Studio)不使用标准的非客户区。虽然这听起来像是XY Problem,但您最终想要完成什么?
-
我想在图片发生变化时保存屏幕截图。虽然前面提到的其实是变化。每当绘图本身发生变化时,我想截屏(保存图片)
-
您是在特别询问 MS Paint 吗?但是,无论哪种方式,您的方法都是脆弱的。即使您识别绘图区域并比较屏幕截图,只要用户使用滚动条移动绘图,您也会得到误报。或者只是更改缩放级别。或者启用/禁用像素网格。
-
不是mspaint,通用解决方案。我只想排除系统菜单更改和文本框控件内的一般光标闪烁
-
您的方法存在根本缺陷。这是行不通的。曾经。使用您提出的算法,每当“有趣区域”的一部分被另一个窗口遮挡或用户决定调整视口大小时,您都会收到更改通知。对于已请求其显示关联为
WDA_MONITOR的窗口或使用 DirectX 渲染表面的窗口,它将失败。你不妨把时间花在解决一个有解决方案的问题上。这不是其中之一。