![窗口和控件閃爍解決方案_第1頁](http://file1.renrendoc.com/fileroot_temp2/2020-12/4/284c984a-b4b7-44c9-bfd3-b8c8799768cd/284c984a-b4b7-44c9-bfd3-b8c8799768cd1.gif)
![窗口和控件閃爍解決方案_第2頁](http://file1.renrendoc.com/fileroot_temp2/2020-12/4/284c984a-b4b7-44c9-bfd3-b8c8799768cd/284c984a-b4b7-44c9-bfd3-b8c8799768cd2.gif)
![窗口和控件閃爍解決方案_第3頁](http://file1.renrendoc.com/fileroot_temp2/2020-12/4/284c984a-b4b7-44c9-bfd3-b8c8799768cd/284c984a-b4b7-44c9-bfd3-b8c8799768cd3.gif)
![窗口和控件閃爍解決方案_第4頁](http://file1.renrendoc.com/fileroot_temp2/2020-12/4/284c984a-b4b7-44c9-bfd3-b8c8799768cd/284c984a-b4b7-44c9-bfd3-b8c8799768cd4.gif)
![窗口和控件閃爍解決方案_第5頁](http://file1.renrendoc.com/fileroot_temp2/2020-12/4/284c984a-b4b7-44c9-bfd3-b8c8799768cd/284c984a-b4b7-44c9-bfd3-b8c8799768cd5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、打斷你們一下,又一位大神,心羽,跟樓上完全兩種不同的風格,他主張全部用貼圖解決問題,也讓我大開眼界,謝謝你,讓我們用最熱烈的掌聲歡迎他, 自繪對話框重繪是會閃, 請問如何避免閃屏? - VC/MFC / 界面 收藏人:峰中之王 2010-10-23|閱:轉(zhuǎn): | 大 中 小 |分享 如果一個程序出現(xiàn)閃爍現(xiàn)象,會讓人覺得程序編寫人員很馬虎,缺乏對細節(jié)的足夠重視。Windows程序的任何部分都沒有任何理由出現(xiàn)閃爍現(xiàn)象。這篇文章的目的是告訴讀者如何使用相關(guān)的技術(shù)防止窗口出現(xiàn)閃爍效果。 什么是閃爍閃爍可以這樣定義:當后面一幅圖像以很快的速度畫在前面一幅圖像上時,在后面圖像顯示前,你可以很快看到前面那一
2、個圖像,這樣的現(xiàn)象就是閃爍。我認為,閃爍會讓使用者對程序很不滿,原因是:如果用戶接口編碼如此糟糕,那么程序的其他部分呢,如何能相信數(shù)據(jù)的正確性呢?一個具有平滑,快速相應的程序會給用戶帶來信心,這個道理很簡單。 程序出現(xiàn)閃爍可以由多種形式造成,最常見的原因是窗口大小發(fā)生改變時,其內(nèi)容重畫造成閃爍。 僅僅畫一次這是一個黃金法則,在任何計算機(Windows或者你使用的任何操作系統(tǒng))上處理畫法邏輯都需要遵循,即永遠不要將同一像素畫兩次。一個懶惰的程序員常常不愿意在畫法邏輯上投入過多精力,而是采用簡單的處理邏輯。要避免閃爍,就需要確保不會出現(xiàn)重復繪制的情況發(fā)生?,F(xiàn)在,WIndows和計算機還是很笨的,
3、除非你給他們指令,否則他們不會做任何事情。如果閃爍的現(xiàn)象發(fā)生,那是因為你的程序刻意地多繪制了屏幕的某些區(qū)域造成的. 這個現(xiàn)象可能是因為一些明確的命令,或者一些被你忽視了的地方。如果程序有閃爍的現(xiàn)象出現(xiàn),你需要你知道如何找到好的方案去解決這個問題。 WM_ERASEBKGND通常,首先需要懷疑的是WM_ERASEBKGND消息。當一個窗口的背景需要被擦除時,這個消息會被發(fā)送。這是因為窗口的繪畫通常經(jīng)歷了兩個過程 WM_ERASEBKGND: 清除背景 WM_PAINT: 在上面繪制內(nèi)容 這兩個過程讓窗體在繪制內(nèi)容時變得很簡單,即:每次當收到WM_PAINT消息時,你知道已經(jīng)有了一個新畫布等待去繪
4、制。然而,畫窗口兩次(一次是通過WM_ERASEBKGND畫背景,另外一次是WM_PAINT)將會導致窗口出現(xiàn)比較糟糕的閃爍現(xiàn)象。只要看看標準的編輯框-打開Windows的寫字板并改變窗口大小,就可以看到那種閃爍的效果。 那么,如何避免窗口背景的重刷呢?有如下兩種方法: 設(shè)置窗口背景刷子為NULL(當注冊Windows類時,設(shè)置WNDCLASS結(jié)構(gòu)中的hbrBackground成員為零) 在WM_ERASEBKGND消息處理時 返回非零值 以上任何一種方法都可以阻止WM_ERASEBKGND 消息去清除窗口。其中,第二個方案的通??梢砸匀缦麓a實現(xiàn): case WM_ERASEBKGND:re
5、turn 1; 當你標記窗口內(nèi)容無效并試圖更新時,還有如下辦法可以防止WM_ERASEBKGND消息:InvalidateRect函數(shù)的最后一個參數(shù)可以指明在下一次窗口重畫時,是否窗口的部分背景會被重刷。將該參數(shù)置為False可以防止當窗口需要重畫時系統(tǒng)發(fā)出WM_ERASEBKGND消息。 InvalidateRect(hwnd, &rect, FALSE); 不該畫的時候一定不要畫有一個比較普遍的現(xiàn)象:即使窗口中只有一個小的部分發(fā)生了改變,往往所有的部分都會被重畫。比如,經(jīng)常地,當窗口大小被改變時,一些(不是所有)的程序會重畫所有的窗口。通常,這是個是不必要的,這是因為當窗口大小被改變時,經(jīng)
6、常是之前窗口的內(nèi)容是不變的,僅僅是改變大小造成的一個小的邊界區(qū)域需要重畫。此時,沒有必要重畫所有區(qū)域。如果在這里多注意,多考慮,就可以使用好的算法以使得一次只有最小的部分被畫。 系統(tǒng)中每個窗口都有更新區(qū)域。這個區(qū)域描述了窗口中變得無效需要重畫的地方。如果一個窗口僅僅其需要更新的區(qū)域,不多繪制其他地方,那么窗口的繪制效果將會非??臁?有幾種方法可以獲得窗口的更新區(qū)域。通過GetUpdateRgn 函數(shù)可以獲得準確的更新區(qū)域,這個函數(shù)返回的結(jié)果可以使矩形的區(qū)域也可以是非矩形的區(qū)域。通過GetUpdateRect 函數(shù)可以獲得需要更新的最小矩形區(qū)域。通常使用矩形的更新區(qū)域比較容易。第三個方法是在Be
7、ginPaint/EndPaint中得到PAINTSTRUCT 結(jié)構(gòu),從而得到準確的更新區(qū)域信息。 一個常規(guī)的畫法函數(shù)是這樣的: PAINTSTRUCT ps;HDC hdc;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);/ do paintingEndPaint(hwnd, &ps);return 0;BeginPaint函數(shù)初始化PS(PAINTSTRUCT)結(jié)構(gòu),其中,成員rcPaint是一個RECT結(jié)構(gòu),描述了包含了需要更新的最小矩形區(qū)域(就像GetWindowRect函數(shù))。如果僅僅在這個矩形區(qū)域上繪制窗口,速度上繪有很好地提高。 現(xiàn)在,當使用B
8、eginPaint/EndPaint時Windows會自動剪切掉畫在更新區(qū)域外面的部分。這意味著,你沒有機會畫到更新區(qū)域以外的地方??赡苣銜J為,如果是這樣的話,花功夫確保代碼不試圖畫到更新區(qū)域外是沒有意義的,反正沒有畫出任何東西來。然而,你仍然可以避免不必要的API調(diào)用和相關(guān)計算,所以,我認為放一些精力在如何工作地更快上是絕對值得的。 如果還是不能解決有些時候,當你花了很多努力去考慮非常好的畫法時,發(fā)現(xiàn)窗口還是會被全部刷新。這通常是由兩個Window 類的屬性造成的:CS_VREDRAW 和 CS_HREDRAW。如果有其中一個標志被設(shè)置時,那么當窗口水平或者豎直方向有大小被改變時,其內(nèi)容每
9、次都會被重新刷新。所有,你需要關(guān)掉這兩個標志,解決的唯一的方式是在創(chuàng)建窗體和窗體類被注冊時,確保這兩個屬性不被設(shè)置。 WNDCLASSEX wc;wc.cbSize = sizeof(wc);wc.style = 0; /* CS_VREDRAW | CS_HREDRAW; */ .RegisterClassEx(&wc);上面的例子描述了當窗體類被注冊時,這兩個屬性不被設(shè)置的實現(xiàn)方法。有一點需要注意:如果主窗體有了這兩個屬性,即使子窗體沒有重畫標志,會導致所有子窗體在其大小被改變時會被重繪。可以通過以下方式避免這個情況發(fā)生: 剪切子窗體有時,閃爍的原因是因為當重畫時,父窗體沒有剪切其子窗體區(qū)
10、域。這樣的結(jié)果導致,整個父窗口內(nèi)容被重畫,而子窗體又被顯示在了上面(造成閃爍)。這個可以通過在父窗體上設(shè)置WS_CLIPCHILDREN 來解決。當這個標志被設(shè)置時,被子窗體占據(jù)的任何區(qū)域?qū)慌懦诟聟^(qū)域外。因此,即使你嘗試在子窗體所在的位置上繪制(父窗口的內(nèi)容),BeginPaint中的剪切區(qū)域也會阻止其繪制效果。 雙緩沖和內(nèi)存設(shè)備描述表(Memory Device Context, 簡稱Memory-DC)常見的徹底避免閃爍的方法是使用雙緩沖。其基本的思路是:將窗體的內(nèi)容畫在屏幕外的一個緩沖區(qū)內(nèi),然后,將該緩沖區(qū)的內(nèi)容再傳遞到屏幕上(使用BilBlt函數(shù))。這是一個非常好的減少閃爍的方
11、法,但是經(jīng)常被濫用,特別是當程序員并不真正地理解如何有效地繪制窗口時。 典型的雙緩沖代碼如下:HDC hdcMem;HBITMAP hbmMem;HANDLE hOld;PAINTSTRUCT ps;HDC hdc;.case WM_PAINT:/ Get DC for windowhdc = BeginPaint(hwnd, &ps);/ Create an off-screen DC for double-bufferinghdcMem = CreateCompatibleDC(hdc);hbmMem = CreateCompatibleBitmap(hdc, win_width, win
12、_height);hOld = SelectObject(hdcMem, hbmMem);/ Draw into hdcMem/ Transfer the off-screen DC to the screenBitBlt(hdc, 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY);/ Free-up the off-screen DCSelectObject(hdcMem, hOld);DeleteObject(hbmMem);DeleteDC (hdcMem);EndPaint(hwnd, &ps);return 0; 這個方法比較慢,
13、因為在每次窗體需要重畫的時候內(nèi)存設(shè)備描述表(Memory-DC)都需要被重新創(chuàng)建。更有效的方法是,僅僅創(chuàng)建內(nèi)存設(shè)備描述表(Memory-DC)一次,并使其足夠大到能滿足任何時候的整個窗體刷新。當程序結(jié)束時,再銷毀這個內(nèi)存設(shè)備描述表(Memory-DC)。這兩種方法都存在對內(nèi)存開銷的問題,特別是如果內(nèi)存設(shè)備描述表(Memory-DC)是針對真?zhèn)€屏幕的大小。雙緩沖也需要兩倍的時間去畫。這是因為其第一次是在內(nèi)存設(shè)備描述表(Memory-DC)上畫,然后再使用BitBlt畫回到屏幕上。當然,好的顯卡會使BitBlt更快,但是仍然會耗CPU 時間。 如果程序需要顯示相當復雜的信息,比如像網(wǎng)頁,那么你應該
14、使用內(nèi)存設(shè)備描述表(Memory-DC)。比如IE,如果不使用雙緩沖,是沒有辦法在繪制網(wǎng)頁時不閃爍的。 沒有必要將雙緩沖技術(shù)用于整個窗體的繪制中??梢赃@樣設(shè)想,窗口中僅僅有一個小部分包含了復雜的圖形對象(比如半透明的位圖或者其他)。你應該將內(nèi)存設(shè)備描述表(Memory-DC)僅僅用于著一個小區(qū)域,其他區(qū)域使用常規(guī)的方法。 有時,通過仔細的思考,經(jīng)常可以避免使用雙緩沖而直接將結(jié)果畫到屏幕上。只要你不破壞黃金法則,即“永遠不要將一個像素畫兩次”,就可以防止閃爍的出現(xiàn)。 避免過度繪制我想說的關(guān)于這個話題是這樣的:有一個需要自己定義畫法的窗體的標題欄。首先,你畫了標題,接著在上面畫一些其他的圖形?,F(xiàn)在
15、,只要標題需要被重畫,就會出現(xiàn)閃爍現(xiàn)象。這是因為你沒有合乎黃金法則。這里,標題被很快地顯示在其他圖形在上面繪制時,導致了閃爍。 有兩種技術(shù)可以組織這種類型的閃爍。第一個是使用剪切,第二個是使用你的大腦。 使用剪切時,你可以使用ExcludeClipRect 函數(shù)在設(shè)備描述表中去標記一個特定的區(qū)域。當一個區(qū)域被標記上時,即使在該區(qū)域上面重畫也不會產(chǎn)生效果。一旦背景已經(jīng)被繪制了,可以通過SelectClipRgn移掉該標記的區(qū)域,其他圖形能被畫到前面標記的區(qū)域上。通過準確的標記(剪切),可以在很多時候被避免過度繪制。 另外一個方案就是找更聰明的解決辦法。比如,當你需要畫一個表格,通常應該先畫空的背
16、景,再畫網(wǎng)格線從而產(chǎn)生表格。但是,這個方法會使網(wǎng)格線產(chǎn)生閃爍,這是因為在網(wǎng)格線被畫之前,下面背景被很快地顯示了一下。然而可以使用不同的做法達到想要的結(jié)果。即,不是一次畫一個大的空背景,而是畫一系列的空方塊,每一個方塊邊是被一個像素的寬度分開。這樣,當畫網(wǎng)格線時,他們剛好能被畫到一個之前沒有畫過的地方。其結(jié)果是不會有閃爍現(xiàn)象,因為沒有像素被畫了超過兩次。 使用你的頭腦去想一個好的算法可能需要長一點的時間,但是卻是值得的,因為這能讓結(jié)果更好。 結(jié)論希望你再也不會問:“為什么我的窗體會閃爍”這樣的問題。我已經(jīng)講解了閃爍的主要原因和解決辦法。如果你遇到了閃爍的問題,你應該能找到原因并且使用這里提到的技
17、術(shù)來解決了窗口和控件閃爍解決方案(2010-07-05 09:42:38)轉(zhuǎn)載標簽:窗口閃爍it分類:開發(fā)對于MFC程序員來說做UI開發(fā)是痛苦的事情,不過大多數(shù)情況下我們都需要做這件事情,因為MFC自帶的控件實在是太簡陋了。這時候我們多半會涉及到自繪控件,隨之而來的很可能就是窗口和控件的閃爍問題。這篇文章希望對MFC的窗口和控件閃爍問題做一個盡量全面的總結(jié)。一、閃爍的原因引起閃爍的原因很多,以至于網(wǎng)上有n多種解決閃爍問題的方法;如果你按照某一種方法做了仍然沒有解決你的問題,請不要認定這個方法有問題,而是你沒有對上號。如果你對這個解釋不滿意的話,我們就來深究一下到底是什么引起了閃爍。從原理上講,
18、閃爍是因為屏幕上連續(xù)的兩次或多次輸出畫面差別比較大引起的,這是最根本的原因。因此如果窗口繪制差別不大,即使刷新再頻繁,也不會引起閃爍。但是差別較大的畫面輸出一定會引起閃爍嗎?還有一個因素要考慮進來,就是屏幕的刷新頻率。根據(jù)顯卡和顯示器的不同,屏幕的刷新周期是不一樣的,雖然這個參數(shù)的差別對界面開發(fā)的影響幾乎可以忽略,但是如果你真的從思想上理解了這一點,你就會立即明白為什么雙緩沖技術(shù)能夠幫助我們解決一部分閃爍問題。二、再談閃爍的原因雖然第一部分的描述對我們有一些啟發(fā),但我們還是應該更深入一些!哪些情況下會導致我們的窗口或控件輸出連續(xù)的差別較大的繪制界面呢?1、繪制界面太復雜,一個刷新周期內(nèi)繪制不完
19、,每次都輸出一部分繪制結(jié)果,導致幾次刷新閃爍。我們的繪制過程都是通過很多個繪制語句組成的,如果這些語句加起來的時間大于一個刷新周期,那么就很可能引起閃爍。通常的解決辦法是去掉中間過程的刷新,直到最后整體繪制完畢再一次性刷新。是不是似曾相識,這就是雙緩沖技術(shù)的原理!但是有些情況是雙緩沖也無能為力的,后面再講。2、繪制過程很簡單,但是需要頻繁刷新。這種情況下我們首先需要弄清楚頻繁刷新的原因是什么,不同的原因?qū)煌慕鉀Q辦法。但是歸根結(jié)底,我們還是為了減少刷新的次數(shù)或者盡量去掉中間輸出差別較大的繪制輸出。3、刷新過程。對于窗口或控件的界面顯示,windows系統(tǒng)有一套繪制和刷新的規(guī)則,繪制或刷新的
20、時機選擇也是影響閃爍的重要因素。如果再與上面兩條結(jié)合起來,某些情況下引起閃爍的原因確實非常復雜。只有我們分析出問題所在,才能用正確的方法解決之。三、幾種消除閃爍的解決方案1、盡量減少重復繪制MFC的窗口和控件刷新有一套很復雜的規(guī)則,如果我們能深入理解,正確應用的話就能避免一部分閃爍。比如盡量用InvalidateRect()函數(shù)代替Invalidate()函數(shù),InvalidateRect()函數(shù)只刷新界面上指定的區(qū)域,如果我們的界面上只有一小部分需要頻繁刷新,那么用這個函數(shù)代替Invalidate()的話,解決閃爍問題的效果是非常明顯的。這個函數(shù)已經(jīng)封裝到MFC的CWnd類中(也有API函數(shù)
21、)。void InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE);其中,lpRect指向一個方形區(qū)域,該區(qū)域?qū)⒈惶砑拥叫枰碌膮^(qū)域列表中,bErase指定刷新時是否更新區(qū)域背景。如果我們需要刷新的區(qū)域是不規(guī)則的,比如是幾個區(qū)域的組合,或者是某區(qū)域中去掉一部分,這時候用InvalidateRect()不能滿足我們的需求,我們可以用InvalidateRgn()函數(shù)。void InvalidateRgn (CRgn* pRgn, BOOL bErase = TRUE);其中,pRgn指向需要刷新的區(qū)域。下面是一段示例代碼:Crect rectCl
22、ient;CRgn rgn1, rgn2;GetClientRect(rectClient);rgn1.CreateRectRgnIndirect(rectClient);rgn2.CreateRectRgnIndirect(m_rectButton);rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR);InvalidateRgn(&rgn1, FALSE);有的時候我們的窗口上有很多控件,如果是由我們負責控件刷新(比如窗口設(shè)置了WS_CLIPCHILDREN風格),我們最好判斷不同情況下確實需要刷新的控件,而不是簡單的將所有控件全部刷新一遍,以此將閃爍的影響減小到最小。
23、2、正確選擇窗口重繪時機Windows有很多刷新和重繪的函數(shù),但是他們的特性和運行方式不盡相同,我們需要了解調(diào)用這些函數(shù)的注意事項,否則很可能因為實際情況跟我們的預期不同而引起閃爍。Windows系統(tǒng)是通過WM_PAINT消息來通知界面重繪的,該消息一般由系統(tǒng)自動產(chǎn)生,比如當窗口被創(chuàng)建、改變大小、最大化、移動、覆蓋等等,另外當UpdateWindow等函數(shù)被調(diào)用時也會產(chǎn)生WM_PAINT消息。當窗口重繪時,并不一定整個窗口區(qū)域都需要刷新,而只是需要更新的那一部分,這部分區(qū)域叫做“無效區(qū)域”。系統(tǒng)在發(fā)現(xiàn)消息隊列空閑時會檢查無效區(qū)域,如果存在就會發(fā)送WM_PAINT消息進行刷新。Invalidat
24、e()、InvalidateRect()、InvalidateRgn()這些函數(shù)都只是產(chǎn)生無效區(qū)域,而并沒有發(fā)送WM_PAINT消息,也就是說我們調(diào)用這些Invalidate()函數(shù)時,并不一定會使窗口立即刷新,而是要等到下次WM_PAINT消息進入到消息隊列時才行。如果要使重繪立即執(zhí)行,可以調(diào)用UpdateWindow()函數(shù)或者RedrawWindow()函數(shù)強制刷新。Windows的窗口重繪時,會首先判斷是否需要刷新背景,如果需要則首先刷新窗口背景,然后進入OnPaint()函數(shù)進行窗口內(nèi)容的繪制。這個過程中如果操作不當,也有可能引起閃爍。當我們遇到閃爍問題,可以從以上窗口繪制機制中查找
25、是否某些步驟的操作引起了閃爍。比如我們在對一個CListCtrl控件進行頻繁操作時(比如添加多個項或者修改內(nèi)容),可以先調(diào)用SetRedraw(FALSE),在操作全部完成后,再調(diào)用SetRedraw(TURE)完成一次性刷新。3、控制窗口背景刷新Windows窗口背景刷新默認情況下是系統(tǒng)幫你完成的,如果我們的窗口繪制內(nèi)容和背景差別比較大,或者在刷新背景和刷新窗口繪制之間有一個明顯的時間間隔,就有可能引起閃爍。這個時候我們可能要禁止系統(tǒng)默認的背景繪制,而在窗口繪制函數(shù)中自行處理背景。這時只要重載OnEraseBkgnd()函數(shù),并直接返回TRUE就可以了,代碼如下:BOOL CMyWnd:On
26、EraseBkgnd(CDC* pDC) returnTRUE; /return CWnd:OnEraseBkgnd(pDC);/注釋掉默認語句4、雙緩沖也許你已經(jīng)聽說過雙緩沖這種方法了,的確,多數(shù)情況下雙緩沖能很好的解決我們的窗口閃爍問題,尤其是涉及到窗口自繪的時候。雙緩沖的基本原理是首先將復雜的繪制結(jié)果輸出到內(nèi)存DC上,然后再一次性輸出到真正的窗口DC,這樣就避免了由于繪制時間占用多個刷新周期,而導致一次繪制引起短時間多次輸出產(chǎn)生閃爍。雙緩沖方法結(jié)合上一個方法,可以解決大部分自繪窗口的閃爍問題。具體的雙緩沖示例代碼如下:void CMyWnd:OnPaint()CPaintDC dc(th
27、is);CRect rectClient;GetClientRect(&rectClient);CDC dcMem;CBitmap bmpMem;dcMem.CreateCompatibleDC(&dc);bmpMem.CreateCompatibleBitmap(&dc,rectClient.Width(),rectClient.Height();dcMem.SelectObject(&bmp);/此處將繪制內(nèi)容輸出到dcMem上/dcMem.FillRect(rectClient,&brush);dc.BitBlt(0,0,rectClient.Width(),rectClient.Hei
28、ght(),&dcMem,0,0,SRCCOPY);bmpMem.DeleteObject();dcMem.DeleteDC(); 5、合理設(shè)置WS_CLIPCHILDREN和WS_CLIPSIBLINGS風格當我們的窗口界面有多層窗口組成時(比如包含多個控件的對話框),用到自繪窗口可能會經(jīng)常碰到閃爍問題。因為多層窗口會涉及到很多遮擋,重繪時一般涉及到主窗口和子窗口等多個窗口,而這些窗口的刷新可能不會在一個刷新周期內(nèi)完成,從而引起閃爍。這時我們可以通過設(shè)置WS_CLIPCHILDREN和WS_CLIPSIBLINGS這兩個窗口風格來控制刷新行為。Clip是裁剪的意思,兩個屬性的具體含義如下:帶
29、有WS_CLIPCHILDREN風格表示裁剪掉子窗口的區(qū)域,即當該窗口重繪時,它的子窗口區(qū)域不刷新,而留給子窗口自己去刷新;帶有WS_CLIPSIBLINGS風格(只用于子窗口)表示裁剪掉兄弟窗口的區(qū)域,即當該窗口重繪時,與兄弟窗口重疊的區(qū)域?qū)⒉粫凰⑿隆8鶕?jù)這些窗口行為,我們就能優(yōu)化我們的界面刷新,控制一些窗口的刷新時機,或者減少重疊區(qū)域的重復刷新。比如當對話框窗口放置了大量控件時,我們可以給對話框加上WS_CLIPCHILDREN風格來阻止一些不必要的刷新。6、多層次窗口調(diào)整大小如果窗口包含很多子窗口,當我們調(diào)整窗口大小時,可能要同時調(diào)整子窗口的位置和大小。此時若使用MoveWindow(
30、)或SetWindowPos()等函數(shù)進行調(diào)整,由于這些函數(shù)會等窗口刷新完才返回,因此當有大量子窗口時,這個過程肯定會引起閃爍。這時我們可以應用BeginDeferWindowPos(), DeferWindowPos()和EndDeferWindowPos()三個函數(shù)解決。首先調(diào)用BeginDeferWindowPos(),設(shè)定需要調(diào)整的窗口個數(shù);然后用DeferWindowPos()移動窗口(并非立即移動窗口);最后調(diào)用EndDeferWindowPos()一次性完成所有窗口的調(diào)整。7、拖動和調(diào)整大小時的虛線框當以上方法無效或者實現(xiàn)起來過于復雜,有沒有更統(tǒng)一更簡潔的方法呢?可能你曾經(jīng)注意到Windows操作系統(tǒng)有這樣一種視覺效果(右擊我的電腦-屬性-高級-設(shè)置-視覺效果-自定義,去掉“拖拉時顯示窗口內(nèi)容”選項),當你拖動和調(diào)整窗口大小時,并不是即時顯示窗口內(nèi)容,而是出現(xiàn)一個虛線框,當調(diào)整結(jié)束時才一次性繪制最終界面。這時一個非常好的防止閃爍的方法,我們來看看怎么實現(xiàn)這種效果。比較復雜的方法是自己畫虛線框,響應WM_MOVING消息畫虛線框,響應WM_MOVE消息繪制窗口內(nèi)容,不過這個方法的難度可想而知,具體內(nèi)容可以查看這個討論帖http:
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年東莞貨車從業(yè)資格證考試試題
- 2024新教材高中政治第二單元經(jīng)濟發(fā)展與社會進步第四課課時1我國的個人收入分配講義+優(yōu)練含解析部編版必修2
- 星球版地理八年級上冊《第一節(jié) 遼闊的疆域》聽課評課記錄3
- 人事主管工作計劃模板
- 業(yè)務委托經(jīng)營協(xié)議
- 煤炭銷售合作協(xié)議書范本
- 房屋漏水維修合同范本
- 北師大版道德與法治七年級下冊10.1《認識競爭》聽課評課記錄
- 哈爾濱商業(yè)大學《國際工程實務》2023-2024學年第二學期期末試卷
- 2024-2025年第二學期班主任工作計劃-育夢蛇年新夢領(lǐng)航班級新程
- 干部家庭社會關(guān)系登記表
- 通信工程制圖(微課版)課程標準
- 四年級下冊數(shù)學知識點總結(jié)
- 第三屆全國石油工程設(shè)計大賽作品(油藏工程設(shè)計單項)
- (人衛(wèi)版第九版?zhèn)魅静W總論(一))課件
- 壓力性損傷護理質(zhì)控細則及集束化管理措施
- 《批判性思維原理和方法》全套教學課件
- 產(chǎn)后康復-腹直肌分離
- 丙烯-危險化學品安全周知卡
- 2024-2030年中國免疫檢查點抑制劑行業(yè)市場研究分析及投資機會預測報告
- 《太常引·建康中秋夜為呂叔潛賦》示范課教學設(shè)計(部編人教版九年級語文下冊)
評論
0/150
提交評論