2012-02-06 131 views
1

我有一個孩子CWind類,在那裏我訂閱的OnPaint事件的:在閃爍的OnPaint

BEGIN_MESSAGE_MAP(MyListBox, CWnd) 
    ON_WM_PAINT() 
END_MESSAGE_MAP() 

如果在OnPaint處理我畫的東西在窗口簡單,像邊境,一切都很好。但如果我添加Sleep(50);(通過這樣做,我模擬一些硬繪製操作),我的窗口將閃爍。我不明白爲什麼會發生這種情況......可能是問題在於OnPaint函數經常被調用,大約每秒2-3次。

更新:我正在使用double biffering:首先,我在PaintDeviceContent中繪製窗口內容,然後將此DC複製到窗口的DC中。

UPDATE2:這裏是代碼:

void CDirectionsListBox::OnPaint() 
{ 
    CRect rectClient; 
    GetClientRect(rectClient); 

    CPaintDC dc(this); // device context for painting 

    CDC DCMem; 
    DCMem.CreateCompatibleDC(&dc); 

    // Draw window here, workign with DCMem 

    dc.BitBlt(0, 0, rectClient.Width(), rectClient.Height(), &DCMem, 0, 0, SRCCOPY); 
} 
+0

請顯示覆制設備上下文的代碼。 – dwo 2012-02-07 20:35:14

回答

1

你的窗口閃爍的原因是因爲它試圖以顯示未畫完還的事情。

使用MFC進行繪圖時,如果繪圖操作不平凡,則需要手動將要繪製的窗口雙緩衝。本質上,你想要做的是在內存中創建一個繪圖上下文,然後畫出來。當繪圖完成時,將在內存上下文中找到的內容複製到窗口上下文中。

+0

我忘了說,我正在使用雙緩衝... – Seekeer 2012-02-06 09:13:00

+0

我相信問題在於你睡在OnPaint模擬複雜的繪圖。如果你使用OnPaint來繪製你想要快速返回的控制權給Windows消息泵。你真的應該在其他地方將圖形繪製到你的後臺緩衝區,並且在OnPaint方法中,只會將後臺緩衝區的內容閃爍到窗口中。 – Dervall 2012-02-06 09:15:41

+0

您建議將「昂貴」的繪圖放在助手方法中,並將其稱爲異步? – Seekeer 2012-02-06 09:25:21

4

默認情況下,通過使用背景畫筆清除客戶區域來繪製背景。你想關閉它。處理WM_ERASEBKGND並且什麼都不做,因爲無論如何你都會在任何現有圖像的頂部溢出。

另請參閱How to avoid flicker while handling WM_ERASEBKGND in Windows dialog

+0

The問題在於每次發生「OnPaint」時都不會發生閃爍。但是如果我增加'OnPaint'執行時間 - 每次都會發生閃爍。 所以我想這是以某種方式與函數執行時間連接,但爲什麼 - 那是我不明白的.. 我已經嘗試處理'WM_ERASEBKGND'但閃爍仍然存在,無關緊要,我返回TRUE或FALSE .. – Seekeer 2012-02-08 06:20:17

+0

This是正確的答案。如果它沒有幫助你,那麼你的實現還有其他一些不相關的問題。 MFC中的雙緩衝大概有三件事:將所有東西繪製成一個位圖(例如'CMemDC'),避免調用基類(或者確保發送'WM_PAINT'消息與緩衝的HDC耦合),返回TRUE 'WM_ERASEBKGND'。 – l33t 2012-02-08 12:18:57

+1

@Seekeer:當然,在blit之前花在'OnPaint'上的時間會影響閃爍,因爲這決定了擦除背景在屏幕上的時間。如果在刷新週期中擦除和擦除,擦除的背景永遠不會超過視頻卡(不會進入物理顯示器)。如果在擦除和blit之間存在延遲,則擦除的屏幕將在顯示器上出現幾幀,並且由用戶注意。 – 2012-02-08 14:49:51