如何正确截屏 Aero/DWM 上的特定窗口
背景信息:我有这个我编写并使用了很长时间的 MFC 应用程序,当用户点击 Print Screen/Alt+Print Screen 键时,它几乎会自动将屏幕截图保存到硬盘上.直到现在我已经使用 Windows 7 RC 几周了,我一直在推迟使用与 Aero 相关的任何东西.
Background info: I have this MFC application I coded and been using for a long time that pretty much automatically saves screenshots to the hard disk when the user hits the Print Screen/Alt+Print Screen key. I have been putting off using anything related to Aero until now that I've been using Windows 7 RC for a couple of weeks.
问题:我正在使用标准的 GetDC/BitBlt 方法来捕获窗口内容.在进行常规全屏抓取时(无论打开多少个窗口等),我对这种方法没有任何问题.当我尝试捕获前景窗口 (Alt+PrintScreen) 时出现问题.这里有两个例子:
The problem: I'm using the standard GetDC/BitBlt method to capture the window contents. I have no problems with this method while doing regular full-screen grabs (no matter how many windows are opened etc). The problem arises when I try capturing the foreground window (Alt+PrintScreen). Here are two examples:
示例 1http://indiecodelabs.com/extern/example1.jpg
示例 2http://indiecodelabs.com/extern/example2.jpg
如您所见,我在边界应有的地方得到了垃圾.这在顶部更加明显,我们可以在两个屏幕截图中看到工具栏的一些重复.
As you can see, I'm getting garbage where the borders should be. This is more noticeable towards the top, where we can see some duplication of the toolbar in both screenshots.
我已经在谷歌上搜索了几个小时,我只能找到一些文章说在 DWM 下 BitBtl/GetDC 方法不起作用,但找不到一个解释我们(开发人员)应该做什么的文章在 DWM 上运行时,我们的应用程序能够保持相同的功能.
I've been googling about this for hours now and all I can find are articles saying that under DWM the BitBtl/GetDC method won't work, but can't find a single one explaining what we (the developers) should do to be able to maintain the same functionality in our apps when running on DWM.
任何帮助、指点、建议将不胜感激.
Any help, pointers, suggestions will be greatly appreciated.
推荐答案
这是一个很好的问题,可惜我不知道确切的答案.我的第一个想法是抓住整个桌面并从中删除有趣的部分.
It's an excellent question that I unfortuneatly don't know exact answer to. My first idea was to grab the whole desktop and cut interesting part out of it.
我已经深入研究了 QT 4.5 的源代码,看看他们是如何做到的,并发现了类似的东西.如果您将 GetClientRect 切换到 GetWindowRect 并剥离 QT 样板代码,您应该得到您想要的.虽然它看起来像一个黑客:)
I've dug into QT 4.5 sources to see how they do it, and found something like this. If you switch GetClientRect to GetWindowRect and strip QT boilerplate code you should get what you want. It looks like a hack though :)
QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
{
RECT r;
GetClientRect(winId, &r);
if (w < 0) w = r.right - r.left;
if (h < 0) h = r.bottom - r.top;
// Create and setup bitmap
HDC display_dc = GetDC(0);
HDC bitmap_dc = CreateCompatibleDC(display_dc);
HBITMAP bitmap = CreateCompatibleBitmap(display_dc, w, h);
HGDIOBJ null_bitmap = SelectObject(bitmap_dc, bitmap);
// copy data
HDC window_dc = GetDC(winId);
BitBlt(bitmap_dc, 0, 0, w, h, window_dc, x, y, SRCCOPY);
// clean up all but bitmap
ReleaseDC(winId, window_dc);
SelectObject(bitmap_dc, null_bitmap);
DeleteDC(bitmap_dc);
QPixmap pixmap = QPixmap::fromWinHBITMAP(bitmap);
DeleteObject(bitmap);
ReleaseDC(0, display_dc);
return pixmap;
}
相关文章