记录屏幕时不出现的奇怪的 MFC/GDI 行为(空白图像)

Odd MFC/GDI behaviour (blank image) that doesn't appear when screen is recorded

本文关键字:GDI 行为 图像 空白 MFC 屏幕 记录      更新时间:2023-10-16

我的程序中有一个奇怪的错误,我正在试图修复,但我真的不知道它可能是什么。我的程序的这一部分有一个对话框,它显示了使用MFC/GDI的各种项目的预览。当我滚动不同的项目时,有时预览图像会消失并变成空白。然而,它:

  • 只在某些机器上发生
  • 显然在Windows 7和XP上都发生
  • 不会每次都在同一物品上发生
  • 项目仍然在那里,当一个人采取截图,但它是空白的,正常查看它。
  • 当我试图用断点跟踪它时,
  • 似乎发生在整个代码的随机位置。它并不总是在相同的位置,屏幕从图像变为空白,这让我相信它不是发生在我的主线程的同一个线程中,即使这是在那一点上唯一没有阻塞的线程。这意味着它发生在一个windows线程中,不是吗?

我假设这是某种竞争条件,但在截图预览的行为,特别是,相当困惑我。为什么在屏幕上看截图的时候是空白的呢?是否存在一些"打印屏幕"机制能够绕过屏幕上显示或更新的内容?

我知道我没有提供太多的信息,人们显然也帮不上什么忙,但如果有人能想到任何事情,我将不胜感激:)

谢谢!

另一种理论:GDI资源泄漏

如果你忘记释放你的GDI对象,奇怪的事情开始发生——包括未绘制的区域。

  1. 运行taskmgr.exe,添加"GDI Objects"列。
  2. 运行软件并监视GDI对象计数。它稳定吗?
  3. 如果您的GDI对象计数不稳定,请查看相关的WM_PAINT处理程序。

下面是一个GDI泄漏的例子:

void CMyWnd::OnPaint()
{
    CPaintDC dc(this);
    dc.SelectObject(&font);
}

选中的GDI对象必须始终取消选中:

void CMyWnd::OnPaint()
{
    CPaintDC dc(this);
    CFont *pOldFont = dc.SelectObject(&font);
    // Use font
    dc.SelectObject(pOldFont);
}

当您记录屏幕时,您是否使用GDI api读取桌面?在这种情况下,任何硬件加速的表面都可能变成黑色(也可能是白色)。要测试这一点,您可以禁用显卡的硬件加速。如果你的录音机开始工作,那么你就找到了罪魁祸首!

要记录这些非gdi表面,你可能需要使用DirectX/OpenGL读取表面。我将从这篇文章开始:http://www.codeproject.com/KB/dialog/screencap.aspx