0

in the OnDraw()-Method i create a Bitmap and blit it to the output every time the window size changes:

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

But every time the application needs to recreate the bitmap in OnDraw(), the Screen gets white until it blits the bitmap to the screen. How can i use the WM_ERASEBKGND-Message to avoid this flickering?

4

2 回答 2

3

我不知道使用 MFC,但使用本机 Windows API,您必须处理WM_ERASEBKGND消息并且简单地return TRUE;. 这告诉默认窗口过程消息已被处理,因此窗口背景被擦除。结果闪烁消失了。

此外,如果您使用函数,请InvalidateRect(..)务必将参数设置bEraseFALSE. 请注意,如果未明确给出,默认情况下该参数为 TRUE。

于 2014-10-31T18:42:42.950 回答
1

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

  1. 当屏幕需要重绘时,从位图中 blit 其内容
  2. 如果底层数据发生变化,启动一个线程将该数据渲染到一个新的位图中(如果该线程已经在运行,只需设置一个标志)
  3. 当渲染线程完成时,将存储的位图与线程结果交换并使窗口无效(如果设置了相应的标志,则立即重新开始渲染)
  4. 当窗口调整大小时触发渲染并将位图拉伸到窗口
  5. 当视图滚动时,blit 那些可用的部分并触发渲染

重要的好处不仅在于您没有闪烁,还在于应用程序在其中的线程忙于将数据呈现为图形时保持响应。在实现中,除了通常的多线程问题外,还有一些重要的事情:

  • 不要一次在后台运行多个线程,因为这会降低性能。如果您只是用鼠标拉伸窗口,您可以轻松生成数十条调整大小的消息,您既不想浪费时间也不想为此浪费内存量。
  • 只渲染可见部分,就像滚动视图的虚拟大小一样,位图会变得非常大。为了使滚动更容易,您可以添加一个框架(例如宽度/高度的 1/5)以保持一些额外的数据可用,同时在后台准备新的位图。
于 2014-10-31T19:12:05.383 回答