Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用PrintWindow截图后,WinAPI窗口不再更新_C++_Winapi_Screenshot - Fatal编程技术网

C++ 使用PrintWindow截图后,WinAPI窗口不再更新

C++ 使用PrintWindow截图后,WinAPI窗口不再更新,c++,winapi,screenshot,C++,Winapi,Screenshot,我正在使用一个应用程序截图。应用程序包含一个listview,一段时间后,列表不再更新。只有当我在列表中选择一个条目时,它才会更新该条目的名称。我的假设是ListView的窗口不会以某种方式失效,但这只是一个猜测。截图后我试着打电话,但也没用 我认为这一定是因为资源泄漏,但我将所有必需的资源封装在一个类中,该类会自动处理释放它们的问题 struct DrawingSurface { DrawingSurface(const DrawingSurface&) = delete; D

我正在使用一个应用程序截图。应用程序包含一个listview,一段时间后,列表不再更新。只有当我在列表中选择一个条目时,它才会更新该条目的名称。我的假设是ListView的窗口不会以某种方式失效,但这只是一个猜测。截图后我试着打电话,但也没用

我认为这一定是因为资源泄漏,但我将所有必需的资源封装在一个类中,该类会自动处理释放它们的问题

struct DrawingSurface
{
  DrawingSurface(const DrawingSurface&) = delete;
  DrawingSurface& operator=(const DrawingSurface&) = delete;

  // Window is a custom class, but it's not really important here.
  DrawingSurface(const Window& window)
  : hwnd(window.handle()), pixels(0), windowDC(0), memoryDC(0), bitmap(0), previous(0)
  {
    // Get window size.
    Rect clientRect = window.getClientRect();
    width = clientRect.width();
    height = clientRect.height();
    // Create DCs.
    windowDC = ::GetDC(window.handle());
    if(windowDC == NULL)
      return;
    memoryDC = ::CreateCompatibleDC(windowDC);
    if(memoryDC == NULL)
      return;
    // Create bitmap.
    ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitmapInfo.bmiHeader.biWidth = width;
    bitmapInfo.bmiHeader.biHeight = -height;
    bitmapInfo.bmiHeader.biPlanes = 1;
    bitmapInfo.bmiHeader.biBitCount = 32;
    bitmapInfo.bmiHeader.biCompression = BI_RGB;
    bitmapInfo.bmiHeader.biSizeImage = width * height * 4;
    bitmap = ::CreateDIBSection(windowDC, &bitmapInfo, DIB_RGB_COLORS, (void**)&pixels, 0, 0);
    if(bitmap == NULL)
      return;
    previous = ::SelectObject(memoryDC, bitmap);
  }
  ~DrawingSurface()
  {
    if(windowDC != NULL)
      ::ReleaseDC(hwnd, windowDC);
    if(previous != NULL && previous != HGDI_ERROR && memoryDC != NULL)
      ::SelectObject(memoryDC, previous);
    if(memoryDC != NULL)
      ::DeleteDC(memoryDC);
    if(bitmap != NULL)
      ::DeleteObject(bitmap);
  }
  bool valid() const
  {
    return width * height > 0
        && previous != NULL
        && previous != HGDI_ERROR
        && windowDC != NULL
        && memoryDC != NULL
        && bitmap != NULL;
  }
  int width, height;
  HWND hwnd;
  HDC windowDC;
  HDC memoryDC;
  HBITMAP bitmap;
  RGBQUAD* pixels;
  BITMAPINFO bitmapInfo;
private:
  HGDIOBJ previous;
};
然后,我使用此绘图面拍摄此功能的屏幕截图:

bool Screenshot::take(const Window& window)
{
  m_width = 0; m_height = 0;
  DrawingSurface surface(window);
  if(!surface.valid())
    return false;
  if(PrintWindow(surface.hwnd, surface.memoryDC, PW_CLIENTONLY) == 0)
    return false;
  if(GdiFlush() == 0)
    return false;
  // Set attributes.
  m_hwnd = surface.hwnd;
  m_width = surface.width;
  m_height = surface.height;
  // Copy pixels.
  m_pixels.resize(surface.width * surface.height, { 0, 0, 0, 0 });
  memcpy(&m_pixels[0], surface.pixels, surface.bitmapInfo.bmiHeader.biSizeImage);
  return true;
}
我看不出我能在这里泄露任何资源。还有什么其他想法可以解释为什么会发生我上面描述的事情


感谢您的帮助。

谢谢大家的回答。我现在能够自己解决这个问题,而这个问题实际上与屏幕截图功能无关。相反,我在列表视图中发布了一条
WM\u KEYDOWN
消息,并且忘记发布
WM\u keydup
。这使ListView处于无效状态,因此不再更新


再次感谢您提供的所有答案,特别是帮助您确认没有资源泄漏。

FYI,
previous
在您的场景中永远不会出现
HGDI\u错误
,因此检查它没有意义。如果
SelectObject()
失败,您应该在构造函数中检查
previous==null
。更重要的是,如果构造函数确实失败,您应该抛出异常,而不是让类处于不稳定状态。这也将允许您摆脱
valid()
。使用任务管理器诊断漏洞,为用户对象和GDI对象添加列。A将大大提高解决此问题的机会。可能不是原因,但您不应该保留
windowDC
(以及相关的
hwnd
)。在构造函数末尾调用
ReleaseDC(window.handle(),windowDC)
以保护资源。我看不到此处显示的代码存在重大问题,因此问题的根源可能位于未显示的代码中。。