Windows使用者介面編程中的介面閃爍問題

來源:互聯網
上載者:User

(XDesigner工作室著作權,轉載請註明出處) 
    在Windows圖形化使用者介面編程中,若程式自己繪製使用者介面時,會經常碰到介面閃爍,比如其他視窗在上面移動,使用者介面滾動,這些都有可能導致閃爍。在一個容器中繪製特定的文檔,需要相應作為繪圖容器的控制項的OnPaint事件,需要在OnPaint事件處理中重新繪製文檔,而Windows作業系統一般會在兩種情況下觸發OnPaint事件:容器控制項被其他表單覆蓋後又顯示,還有就是容器控制項的滾動處理。在這些情況下,Windows作業系統會頻繁的觸發OnPaint事件,而應用程式會頻繁的在繪圖容器中重新繪製圖形,若應用程式沒有進行很好的最佳化,則很有可能導致使用者介面閃爍。

   使用者介面出現閃爍自然害處多多,首先它使得你的程式看起來不專業,甚至有不穩定的嫌疑,對於追求完美的你這麼會容許它的存在呢;其次閃爍會損害使用者的視力,容易讓使用者產生視覺疲勞。

    好了,廢話我不多說了,我們就來發現問題,分析問題,解決問題。

    首先說說閃爍的本質,說到本質,就不得不提一些電腦系統結構和Windows圖形使用者子系統的一些知識。我們知道,在電腦記憶體中有一個地區叫做顯存,而顯卡則每過一些毫秒就從掃描顯存,然後根據操作顯示器來繪製一個個象素,因此每過一些毫秒顯示器顯示的內容就會重新設定一遍,由於這是硬體操作,非常快,若畫面內容沒有變化,則人類肉眼是看不到這個重新整理的,此時使用者介面是沒有任何閃爍。

         右圖就是應用程式繪製使用者介面的原理,應用程式在CPU的支援下向顯存填充資料,而以此同時顯卡也從顯存載入資料操作顯示器繪製圖形,(筆者想若應用程式能直接存取顯示器則繪製速度不要太快哦),而使用者介面閃爍也就根源於這種顯示結構。前面提到,顯卡每過一些毫秒就會掃描顯存,重新整理顯示器的顯示。假設有個顯示卡,設定其重新整理頻率為50赫茲,則它每20毫秒就掃描顯存重新整理顯示器,而顯卡的操作和應用程式的操作之間沒有任何關係,顯卡是內建處理器的,於是應用程式和顯卡這兩個對象同時操作顯存,顯卡唯讀取顯存,而應用程式則修改顯存,這就導致了類似多線程程式的資料同步的問題了。但這時硬體結構決定此時沒有什麼鎖定機制可使用。顯卡每20毫秒就進行重新整理操作,連作業系統也擋不住,而且應用程式根本不知道顯卡會何時進行重新整理操作。

    某個時刻,應用程式需要繪製使用者介面,首先需要清空繪製容器,因此將顯存一大片地區設定為白色,應用程式剛完成了清空操作,還每來得及繪製內容時,顯卡就重新整理了,很快顯示器上顯示了一大片白色。同時,應用程式開始繪製內容,應用程式運行緩慢,它化了20毫秒繪製了文檔的上半身,文檔上半身主要為紅色,剛繪製了上半身,顯卡就好不留情的進行重新整理,很快顯示器上顯示了一半的文檔,剛才一半的白色大半變成了紅色,此時使用者看來,顯示器一下變成一片白,然後很快一半變成紅色,此時顯示器內容產生了兩次大面積的內容變幻,然後應用程式又化了20毫秒顯示了文檔的下半身,文檔下半身主要為綠色,此時顯卡進行重新整理,顯示器上另一半還殘存的白色又變成綠色。由於應用程式繪製文檔完畢,因此不再修改顯存,此時顯示器的顯示的內容不再發生改變。

    在上面的描述中,顯示器首先從花花綠綠變成一片白,20毫秒後一半變成紅色,又20毫秒後另一半變成綠色,如此大面積的顯示內容短期的改變就是所謂的閃爍,此時電腦顯示器就是在折磨使用者的眼睛。

    其實從廣義上說,電腦顯示器顯示的內容頻繁的發生大面積的改變都是考驗人類的眼睛。有些人玩一些激烈的3D遊戲,比如雷神CS之類的,若玩的時間長點眼睛就受不了。就是因為這些遊戲程式導致顯示器顯示的內容頻繁的發生大面積的改變。因此遊戲程式也算導致使用者介面閃爍。只不過這種閃爍不算難受。

    通過上面的討論,知道了閃爍的根源,於是我們發現了問題,並分析了問題,現在解決問題。在目前的電腦結構中,我們的應用程式只能通過填充顯存來繪製使用者介面,在這種情況下,對付閃爍的不二法則就是快,應用程式要非常快的修改顯存。對於每20毫秒進行重新整理操作的顯卡,若我們的應用程式能在20毫秒內修改顯存完畢,則在很多情況下顯卡就只會導致顯示器顯示的內容發生改變,減少閃爍,應用程式填充顯存前後顯存的資料進行對比,若資料前後不一致的位元組數越少,顯示器中重新整理操作前後顏色發生改變的象素數就越少,這使用者介面的閃爍就越小。

    提高應用程式修改顯存的速度的方法有很多中,而且Windows作業系統為我們做了許多底層的操作。我們知道若一個表單被覆蓋後又顯示了,則Windows作業系統就會向該表單發送重繪訊息,而且還會傳一個矩形資料,該矩形表示表單中需要重新整理的地區,應用程式可以根據這個矩形來重新繪製文檔的某個部分,這樣就不必要繪製所有的內容,提高繪製速度,減少繪製時間,這就需要進行繪圖代碼的最佳化。

   在某些情況下,繪圖速度很難最佳化起來,此時可以採用所謂“雙緩衝”的技術來減少閃爍,應用程式可以在記憶體中建立一個和螢幕相相容的圖形裝置上下文。該上下文實際上處理一個儲存在記憶體中的BMP圖片對象,這樣就容許應用程式緩慢地在這個BMP上繪製圖形。應用程式繪製完畢,就用WIN32API函數BitBlt來將BMP圖片填充到顯存中,BitBlt函數速度非常快,足以在螢幕的重新整理周期內完成繪圖,這樣能基本上避免閃爍。但雙緩衝也有缺點,首先增加程式複雜度,其次要消耗一些記憶體,還有它讓整個繪圖時間變長,導致使用者進行滾動時會產生“介面沉重感”,有“慣性”,此外還讓人偷懶而不注意繪圖操作的最佳化。

      俗話說,說得容量做到難,編程也一樣,本文中對付閃爍的說的輕巧,但在實際編程中,閃爍一直是圖形化使用者介面編程的老大難問題,需要精心的設計程式結構,最佳化代碼,提高速度。這需要靠很多的理論知識和深厚的編程功底,這些需要長期的編程實踐。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.