简体   繁体   English

使用PrintWindow截屏后,WinAPI Window不再更新

[英]WinAPI Window does not update anymore after taking screenshot with PrintWindow

I am taking screenshots of an application using PrintWindow() . 我正在使用PrintWindow()拍摄应用程序的屏幕截图。 The application contains a listview and after some time, the list does not update anymore. 该应用程序包含一个列表视图,一段时间后,该列表不再更新。 Only when I select an entry in the list, does it update the name of that entry. 仅当我在列表中选择一个条目时,它才会更新该条目的名称。 My assumption is that the ListView's window does not get invalidated somehow, but that's just a guess. 我的假设是ListView的窗口不会以某种方式失效,但这只是一个猜测。 I tried calling InvalidateRect() after taking the screenshot, but that doesn't help either. 我尝试在截屏后调用InvalidateRect() ,但这也无济于事。

I thought the reason for this must be a resource leak, but I encapsulated all required resources in a class, that automatically handles releasing them. 我以为这样做的原因一定是资源泄漏,但是我将所有必需的资源封装在一个类中,该类会自动处理释放这些资源。

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;
};

I then use this drawing surface to take a screenshot with this function: 然后,我使用此绘图表面使用此功能截屏:

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;
}

I don't see where I could leak any resources here. 我看不到在哪里可以泄漏任何资源。 Any other ideas why what I described above might happen? 还有其他任何想法可能会导致我上面描述的事情发生吗?

Any help appreciated, thanks. 任何帮助表示赞赏,谢谢。

Thanks everyone for the answers. 谢谢大家的回答。 I was able to solve this myself now and the problem really wasn't related to the screenshot function. 我现在可以自己解决此问题,而该问题确实与屏幕截图功能无关。 Instead I had posted a WM_KEYDOWN message to the ListView, and forgot to post WM_KEYUP as well. 相反,我已经将WM_KEYDOWN消息发布到ListView,并且也忘记了发布WM_KEYUP This left the ListView in an invalid state and therefore it did not update anymore. 这使ListView处于无效状态,因此不再更新。

Thanks again for all the answers and especially for helping to verify that there are no resources leaked. 再次感谢您提供所有答案,尤其是感谢您帮助确认没有资源泄漏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM