2014-10-31 85 views
0

使用WM_ERASEBKGND-消息閃爍 - 方法I創建一個位圖,它BitBlt到每次輸出的窗口大小的變化:C++:避免​​在的OnDraw()MFC-應用

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消息來避免這種閃爍?

回答

2

我不知道與MFC,但與本機的Windows API,你必須處理WM_ERASEBKGND消息和簡單return TRUE;。這告訴默認窗口過程消息被處理,因此窗口背景被擦除。結果,閃爍消失。

此外,如果您使用功能InvalidateRect(..)請務必將參數bErase設置爲FALSE。請注意,如果沒有明確給出,參數默認爲TRUE。

+0

[Here](http://msdn.microsoft.com/nl-be/library/sk92a2ws.aspx)是MFC的版本。 – Vincent 2014-10-31 19:10:16

1

在一種應用中,其中呈現窗口內容採取非平凡的時間量我採取了以下步驟:

  1. 當屏幕需要一個重繪,從位圖的blit其內容
  2. 如果基礎數據的變化,啓動一個線程將該數據渲染成一個新的位圖(如果該線程已經運行,只需設置一個標誌)
  3. 當渲染線程完成時,將存儲的位圖與線程結果交換並使窗口無效(如果根據標誌設置,馬上重新開始渲染)
  4. 當調整窗口大小時觸發渲染和拉伸的blit位圖到窗口
  5. 當視圖被滾動,的blit那些可用的零件,引發渲染

重要的好處不只是你沒有閃爍,而且應用程序保持響應,而線程正忙於將數據呈現爲圖形。在實現中,除了通常的多線程問題之外,還有一些重要的事情:

  • 不要一次在後臺運行多個線程,因爲這可能會降低性能。如果你只是用鼠標拉伸窗口,你可以輕鬆地生成幾十個調整大小的消息,你不想浪費時間和內存的數量。
  • 只渲染可見部分,與scrollview的虛擬大小一樣,位圖可能變得非常大。爲了使滾動更容易,您可以添加一個框架(例如寬度/高度的1/5)以在後臺準備新的位圖時保留一些額外的數據。