C ++:使用MFC-Application中的WM_ERASEBKGND-Message避免闪烁

时间:2014-10-31 18:36:31

标签: c++ mfc erase blit bitblit

在OnDraw()中的

- 方法我创建一个Bitmap并在每次窗口大小改变时将它blit到输出:

void CmbmView::OnDraw(CDC* pDC)
{
  CRect WindowSize;
  HDC hdc;
  BITMAPINFO pbmi;
  HBITMAP hbm;
  CBitmap *pBitmap;
  CDC MemDC;
  void* ppvBits;

  GetClientRect(WindowSize);

  hdc = CreateDC (TEXT ("DISPLAY"), NULL, NULL, NULL) ;

  memset(&pbmi, 0, sizeof(BITMAPINFO));
  pbmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  pbmi.bmiHeader.biWidth = WindowSize.Width();
  pbmi.bmiHeader.biHeight = -WindowSize.Height(); // top down
  pbmi.bmiHeader.biPlanes = 1;
  pbmi.bmiHeader.biBitCount = 32;
  pbmi.bmiHeader.biCompression = BI_RGB;

  hbm = CreateDIBSection(hdc, &pbmi, DIB_RGB_COLORS, &ppvBits, NULL, NULL);
  pBitmap = CBitmap::FromHandle(hbm);

  MemDC.CreateCompatibleDC(pDC); 
  MemDC.SelectObject(pBitmap);

  // "Draw" into ppvBits
  GetDocument()->DrawApple(pDC, ppvBits, WindowSize.Width(), WindowSize.Height(), m_MaxIter, m_MaxBetragQuadrat, m_BW);

  // Blit it to the output
  pDC->BitBlt(0, 0, WindowSize.Width(), WindowSize.Height(), &MemDC, 0, 0, SRCCOPY);
}

但每次应用程序需要在OnDraw()中重新创建位图时,屏幕会变为白色,直到它将位图闪烁到屏幕。如何使用WM_ERASEBKGND-Message来避免这种闪烁?

2 个答案:

答案 0 :(得分:2)

我不了解MFC,但使用原生Windows API,您必须处理WM_ERASEBKGND消息,只需return TRUE;。这告诉默认窗口过程消息被处理因此窗口背景被擦除。结果闪烁消失了。

此外,如果您正在使用功能InvalidateRect(..),请务必将参数bErase设置为FALSE。请注意,如果未明确指定,则参数默认为TRUE。

答案 1 :(得分:1)

在渲染窗口内容花费了大量时间的应用程序中,我采取了以下步骤:

  1. 当屏幕需要重绘时,从位图blit其内容
  2. 如果基础数据发生变化,则启动一个线程将该数据呈现为一个新的位图(如果该线程已在运行,只需设置一个标志)
  3. 当渲染线程完成时,用线程结果交换存储的位图并使窗口无效(如果设置了相应的标志,立即重新开始渲染)
  4. 调整窗口大小时触发渲染并将位图拉伸到窗口
  5. 滚动视图时,将那些可用的部分blit并触发渲染
  6. 重要的好处不仅在于您没有闪烁,而且应用程序在其中的线程忙于将数据渲染为图形时仍保持响应。在实现中,除了通常的多线程问题外,还有一些重要的事情:

    • 不要立即在后台运行多个线程,因为这会降低性能。如果你只是用鼠标拉伸窗口,你可以轻松生成数十个调整大小的消息,你既不想浪费时间也不想浪费时间。
    • 仅渲染可见部分,与滚动视图的虚拟大小一样,位图可能变得非常大。为了使滚动更容易,您可以添加一个框架(例如宽度/高度的1/5),以便在后台准备新的位图时保留一些额外的数据。