【问题标题】:How to capture the screen with the "Tool Tips"?如何使用“工具提示”截屏?
【发布时间】:2015-07-17 12:50:53
【问题描述】:

我正在使用 GDI 捕获屏幕,我注意到屏幕截图中没有包含“工具提示”。这是我的基本代码:

HDC hdcDesk = GetDC(0);

HDC hdcMem = CreateCompatibleDC(hdcDesk);
HBITMAP hbmMem = CreateCompatibleBitmap(hdcDesk, 1920, 1080);
SelectObject(hdcMem, hbmMem);

StretchBlt(hdcMem, 0, 0, 1920, 1080, hdcDesk, 0, 0, 1920, 1080, SRCCOPY);

// Now save the bitmap...

这可以解决吗,还是我应该使用其他方法来捕获屏幕(GDI 除外)?


编辑:

这是我拍摄的不显示工具提示的屏幕截图。

【问题讨论】:

  • 尝试 SRCCOPY | CAPTUREBLT ?
  • 你的程序可能是被鼠标或键盘激活的,它会在别处关闭工具提示。
  • 您需要确保屏幕捕获程序不会接管焦点,不要摆弄任何输入(如鼠标)。查看屏幕捕获程序的所有部分。如果捕获软件使用计时器,这可能是最好的镜头。您激活捕获软件,调出工具提示并等待。如果没有关注焦点和输入,你应该是黄金。
  • 这似乎是 Window XP 特有的。我在 Windows 8 上运行良好,屏幕截图抓住了一切。
  • @Csaba Toth 当我截屏时工具提示仍然存在。我相信正如 Barmak Shemirani 所说,这是一个 XP 问题。但是有谁知道为什么这个问题只存在于 XP 中?

标签: c++ c winapi gdi


【解决方案1】:

更新:根据 Alex K.、Adrian McCarthy 等人的建议添加了 CAPTUREBLT

我无法重现同样的问题。如果您成功拍摄了桌面屏幕截图,那么一切都应该在那里!试试这个代码。请注意,等待 3 秒应该让您有时间手动激活工具提示。

SetProcessDPIAware();
HDC hdc = GetDC(HWND_DESKTOP);
RECT rc; GetWindowRect(GetDesktopWindow(), &rc);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;

HBITMAP hbitmap = CreateCompatibleBitmap(hdc, width, height);
HDC memdc = CreateCompatibleDC(hdc);
HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, width, height, hdc, 0, 0, CAPTUREBLT | SRCCOPY);

WORD bpp = 24; //save 24-bit bitmap
DWORD size = ((width * bpp + 31) / 32) * 4 * height;
BITMAPFILEHEADER filehdr = { 'MB', 54 + size, 0, 0, 54 };
BITMAPINFOHEADER infohdr = { 40, width, height, 1, bpp };
BYTE* pix = malloc(size); 
GetDIBits(hdc, hbitmap, 0, height, pix, (BITMAPINFO*)&infohdr, DIB_RGB_COLORS);

FILE* fout = fopen("c:\\test\\_bmp.bmp", "wb"); 
if (fout) //save to file
{
    fwrite(&filehdr, sizeof(filehdr), 1, fout);
    fwrite(&infohdr, sizeof(infohdr), 1, fout);
    fwrite(pix, 1, size, fout);
    fclose(fout);
}

//cleanup
free(pix);
SelectObject(memdc, oldbmp);
DeleteObject(memdc);
DeleteObject(hbitmap);
ReleaseDC(HWND_DESKTOP, hdc);

【讨论】:

  • 根据 Alex K. 的评论尝试 SRCCOPY | CAPTUREBLT。这对我一直有效
  • 尽管现代版本的 Windows 更宽容,但在销毁 bmp 之前从 memdc 中选择 bmp 仍然是一个好习惯。其实在调用GetDIBits之前应该从memdc中选择出来。根据 MSDN,“当应用程序调用此函数时,不得将由 hbmp 参数标识的位图选择到设备上下文中。”
  • @paul 在 Windows 7 中相同。在我使用 Adrian McCarthy 的评论之前,这个答案(针对 C 进行了修改)没有捕获工具提示,现在它可以工作了,得到了支持。
  • 更多关于不从 DC 中选择对象的后果:blogs.msdn.com/b/oldnewthing/archive/2013/03/06/10399678.aspx
【解决方案2】:

几年前我在使用 Windows XP 系统时遇到了确切的问题。我的问题答案中的代码解决了这个问题:

Capture screenshot Including Semitransparent windows in .NET

对您而言,您应该可以将您的 stretchblt 行更改为 bitblt 并添加 captureblt:

HDC hdcDesk = GetDC(0);

HDC hdcMem = CreateCompatibleDC(hdcDesk);
HBITMAP hbmMem = CreateCompatibleBitmap(hdcDesk, 1920, 1080);
SelectObject(hdcMem, hbmMem);

BitBlt(hdcMem, 0, 0, 1920, 1080, hdcDesk, 0, 0, SRCCOPY | CAPTUREBLT);

// Now save the bitmap...

工具提示,如透明窗口,被 bitblt 规范跳过。另外,您没有调整大小,因此请使用 bitblt。如果这不起作用,那么正如其他评论者所暗示的那样,您正在做的事情可能有其他问题,因此您可以将我的问题的答案从 C# 转换为 C,这在 XP 上对我有用。 (当然我没有 XP 可以测试了,但这绝对是问题所在)。

【讨论】:

    猜你喜欢
    • 2011-05-02
    • 1970-01-01
    • 2019-05-12
    • 2018-01-28
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 2016-09-30
    相关资源
    最近更新 更多