Windows用戶界面編程中的界面閃爍問題
在Windows圖形化用戶界面編程中,若程序自己繪制用戶界面時,會經常碰到界面閃爍,比如其他窗口在上面移動,用戶界面滾動,這些都有可能導致閃爍。在一個容器中繪制特定的文檔,需要相應作為繪圖容器的控件的OnPaint事件,需要在OnPaint事件處理中重新繪制文檔,而Windows操作系統一般會在兩種情況下觸發OnPaint事件:容器控件被其他窗體覆蓋後又顯示,還有就是容器控件的滾動處理。在這些情況下,Windows操作系統會頻繁的觸發OnPaint事件,而應用程序會頻繁的在繪圖容器中重新繪制圖形,若應用程序沒有進行很好的優化,則很有可能導致用戶界面閃爍。
用戶界面出現閃爍自然害處多多,首先它使得你的程序看起來不專業,甚至有不穩定的嫌疑,對於追求完美的你這麼會容許它的存在呢;其次閃爍會損害用戶的視力,容易讓用戶產生視覺疲勞。
好了,廢話我不多說了,我們就來發現問題,分析問題,解決問題。
首先說說閃爍的本質,說到本質,就不得不提一些計算機系統結構和Windows圖形用戶子系統的一些知識。我們知道,在計算機內存中有一個區域叫做顯存,而顯卡則每過一些毫秒就從掃描顯存,然後根據操作顯示器來繪制一個個象素,因此每過一些毫秒顯示器顯示的內容就會重新設置一遍,由於這是硬件操作,非常快,若畫面內容沒有變化,則人類肉眼是看不到這個刷新的,此時用戶界面是沒有任何閃爍。
右圖就是應用程序繪制用戶界面的原理,應用程序在CPU的支持下向顯存填充數據,而以此同時顯卡也從顯存加載數據操作顯示器繪制圖形,(筆者想若應用程序能直接訪問顯示器則繪制速度不要太快哦),而用戶界面閃爍也就根源於這種顯示結構。前面提到,顯卡每過一些毫秒就會掃描顯存,刷新顯示器的顯示。假設有個顯示卡,設置其刷新頻率為50赫茲,則它每20毫秒就掃描顯存刷新顯示器,而顯卡的操作和應用程序的操作和應用程序的操作之間沒有任何關系,顯卡是自帶處理器的,於是應用程序和顯卡這兩個對象同時操作顯存,顯卡只讀取顯存,而應用程序則修改顯存,這就導致了類似多線程程序的數據同步的問題了。但這時硬件結構決定此時沒有什麼鎖定機制可使用。顯卡每20毫秒就進行刷新操作,連操作系統也擋不住,而且應用程序根本不知道顯卡會何時進行刷新操作。
某個時刻,應用程序需要繪制用戶界面,首先需要清空繪制容器,因此將顯存一大片區域設置為白色,應用程序剛完成了清空操作,還每來得及繪制內容時,顯卡就刷新了,很快顯示器上顯示了一大片白色。同時,應用程序開始繪制內容,應用程序運行緩慢,它化了20毫秒繪制了文檔的上半身,文檔上半身主要為紅色,剛繪制了上半身,顯卡就好不留情的進行刷新,很快顯示器上顯示了一半的文檔,剛才一半的白色大半變成了紅色,此時用戶看來,顯示器一下變成一片白,然後很快一半變成紅色,此時顯示器內容產生了兩次大面積的內容變幻,然後應用程序又化了20毫秒顯示了文檔的下半身,文檔下半身主要為綠色,此時顯卡進行刷新,顯示器上另一半還殘存的白色又變成綠色。由於應用程序繪制文檔完畢,因此不再修改顯存,此時顯示器的顯示的內容不再發生改變。