gpt4 book ai didi

mfc - 如何正确捕获 Aero/DWM 上的特定窗口

转载 作者:行者123 更新时间:2023-12-02 06:54:22 28 4
gpt4 key购买 nike

背景信息:我编写了这个 MFC 应用程序并使用了很长时间,当用户按下 Print Screen/Alt+Print Screen 键时,它几乎会自动将屏幕截图保存到硬盘。我一直推迟使用任何与 Aero 相关的东西,直到现在我已经使用 Windows 7 RC 几个星期了。

问题:我使用标准 GetDC/BitBlt 方法来捕获窗口内容。在进行常规全屏抓取时(无论打开多少个窗口等),我对这种方法没有任何问题。当我 try catch 前景窗口(Alt+PrintScreen)时出现问题。以下是两个示例:

示例1 http://indiecodelabs.com/extern/example1.jpg

示例2 http://indiecodelabs.com/extern/example2.jpg

正如你所看到的,我在边界应该在的地方得到了垃圾。这在顶部更加明显,我们可以在两个屏幕截图中看到工具栏的一些重复。

我已经在谷歌上搜索了几个小时,我所能找到的都是文章说在 DWM 下 BitBtl/GetDC 方法不起作用,但找不到一篇解释我们(开发人员)应该做什么的文章为了能够在 DWM 上运行时保持我们的应用程序中的相同功能。

任何帮助、指点、建议将不胜感激。

最佳答案

BOOL CaptureWindow(const CString& filename)
{
HWND hWnd = NULL;
hWnd = ::GetForegroundWindow();
if(!hWnd)
{
return FALSE;
}
CRect rect;
GetWindowRect(hWnd, &rect);
rect.NormalizeRect();
return DoCapture(CPoint(rect.left, rect.top), CSize(rect.Width(), rect.Height()), filename);
}

BOOL DoCapture(const POINT& coords, const SIZE& areaSize, const CString& filename)
{
CDC dc;
HDC hdc = GetDC(NULL); // <-- We use this instead of GetWindowDC.
// This is the only thing I had to change other than
// getting the window coordinates in CaptureWindow()
dc.Attach(hdc);

// Create a memory DC into which the bitmap will be captured
CDC memDC;
memDC.CreateCompatibleDC(&dc);

// If there is already a bitmap, delete it as we are going to replace it
CBitmap bmp;
bmp.DeleteObject();

ICONINFO info;
GetIconInfo((HICON)::GetCursor(), &info);

CURSORINFO cursor;
cursor.cbSize = sizeof(CURSORINFO);
GetCursorInfo(&cursor);

bmp.CreateCompatibleBitmap(&dc, areaSize.cx, areaSize.cy);
CBitmap * oldbm = memDC.SelectObject(&bmp);

// Before we copy the image in, we blank the bitmap to
// the background fill color
memDC.FillSolidRect(&CRect(0,0,areaSize.cx, areaSize.cy), RGB(255,255,255));

// Copy the window image from the window DC into the memory DC
memDC.BitBlt(0, 0, areaSize.cx, areaSize.cy, &dc, coords.x, coords.y, SRCCOPY|CAPTUREBLT);

// This part captures the mouse cursor and paints it on the image.
if(programSettings.bWantCursor)
{
int osVersion = OSCheck::GetMajorOSVersion(); // For some reason cursor icons in
// versions older than Vista are not
// top-aligned. So we compensate.
int offsetX = (osVersion >= 6) ? 0 : 10;
int offsetY = (osVersion >= 6) ? 0 : 10;

CPoint cursorOffset(cursor.ptScreenPos.x - coords.x - offsetX, cursor.ptScreenPos.y - coords.y - offsetY);

// Now draw the image of the cursor that we captured during
// the mouse move. DrawIcon will draw a cursor as well.
memDC.DrawIcon(cursorOffset, (HICON)cursor.hCursor);
}
memDC.SelectObject(oldbm);

Bitmap outputBitMap(bmp, NULL);

// Optionally copy the image to the clipboard.
if(programSettings.bWantClipboard)
{
if(OpenClipboard(NULL))
{
EmptyClipboard();
SetClipboardData(CF_BITMAP, bmp);
CloseClipboard();
}
}

BOOL success = DumpImage(&outputBitMap, filename);

DeleteObject(bmp.Detach());
DeleteDC(dc.Detach());
DeleteDC(memDC.Detach());
return success;
}

供引用:DumpImage 几乎使用 Gdi::Bitmap 的 Save 方法。它已被省略,因为它具有一些与示例无关的特定于应用程序的代码。另外一个额外的好处是,如果您想知道如何将光标包含在屏幕截图中,那么代码也在那里。希望能帮助到你。另外值得一提的是,与传统方法相反,这还将包括捕获窗口顶部可能有的任何重叠窗口。另外,如果您使用此代码进行全屏捕获,请注意它不会捕获视频游戏窗口。我实际上想知道如何正确地做到这一点,而不必求助于 DirectX。这仅影响在 Aero 模式下运行的 Windows Vista/7。

关于mfc - 如何正确捕获 Aero/DWM 上的特定窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1149271/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com