欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      雙緩存解決閃爍及對(duì)話框背景覆蓋控件問題 (WINDOWS API)

      時(shí)間:2019-05-12 19:46:00下載本文作者:會(huì)員上傳
      簡介:寫寫幫文庫小編為你整理了多篇相關(guān)的《雙緩存解決閃爍及對(duì)話框背景覆蓋控件問題 (WINDOWS API)》,但愿對(duì)你工作學(xué)習(xí)有幫助,當(dāng)然你在寫寫幫文庫還可以找到更多《雙緩存解決閃爍及對(duì)話框背景覆蓋控件問題 (WINDOWS API)》。

      第一篇:雙緩存解決閃爍及對(duì)話框背景覆蓋控件問題 (WINDOWS API)

      一、閃爍問題。

      閃爍問題在MFC窗體中經(jīng)常見到。在網(wǎng)上碰到這些問題的層次不窮,解決方法也是多樣的!但是最經(jīng)典也最耐用的還是靠用雙緩存解決!首先讓我們來了解一下,為什么會(huì)產(chǎn)生屏幕閃爍問題:閃爍可以這樣定義:當(dāng)后面一幅圖像以很快的速度畫在前面一幅圖像上時(shí),在后面圖像顯示前,你可以很快看到前面那一個(gè)圖像,這樣的現(xiàn)象就是閃爍。我認(rèn)為,閃爍會(huì)讓使用者對(duì)程序很不滿,原因是:如果用戶接口編碼如此糟糕,那么程序的其他部分呢,如何能相信數(shù)據(jù)的正確性呢?一個(gè)具有平滑,快速相應(yīng)的程序會(huì)給用戶帶來信心,這個(gè)道理很簡單。程序出現(xiàn)閃爍可以由多種形式造成,最常見的原因是窗口大小發(fā)生改變時(shí),其內(nèi)容重畫造成閃爍。

      僅僅畫一次

      這是一個(gè)黃金法則,在任何計(jì)算機(jī)(Windows或者你使用的任何操作系統(tǒng))上處理畫法邏輯都需要遵循,即永遠(yuǎn)不要將同一像素畫兩次。一個(gè)懶惰的程序員常常不愿意在畫法邏輯上投入過多精力,而是采用簡單的處理邏輯。要避免閃爍,就需要確保不會(huì)出現(xiàn)重復(fù)繪制的情況發(fā)生。現(xiàn)在,WIndows和計(jì)算機(jī)還是很笨的,除非你給他們指令,否則他們不會(huì)做任何事情。如果閃爍的現(xiàn)象發(fā)生,那是因?yàn)槟愕某绦蚩桃獾囟嗬L制了屏幕的某些區(qū)域造成的.這個(gè)現(xiàn)象可能是因?yàn)橐恍┟鞔_的命令,或者一些被你忽視了的地方。如果程序有閃爍的現(xiàn)象出現(xiàn),你需要你知道如何找到好的方案去解決這個(gè)問題。

      WM_ERASEBKGND 通常,首先需要懷疑的是WM_ERASEBKGND消息。當(dāng)一個(gè)窗口的背景需要被擦除時(shí),這個(gè)消息會(huì)被發(fā)送。這是因?yàn)榇翱诘睦L畫通常經(jīng)歷了兩個(gè)過程

      WM_ERASEBKGND: 清除背景 WM_PAINT: 在上面繪制內(nèi)容

      這兩個(gè)過程讓窗體在繪制內(nèi)容時(shí)變得很簡單,即:每次當(dāng)收到WM_PAINT消息時(shí),你知道已經(jīng)有了一個(gè)新畫布等待去繪制。然而,畫窗口兩次(一次是通過WM_ERASEBKGND畫背景,另外一次是WM_PAINT)將會(huì)導(dǎo)致窗口出現(xiàn)比較糟糕的閃爍現(xiàn)象。只要看看標(biāo)準(zhǔn)的編輯框-打開Windows的寫字板并改變窗口大小,就可以看到那種閃爍的效果。

      那么,如何避免窗口背景的重刷呢?有如下兩種方法:

      設(shè)置窗口背景刷子為NULL(當(dāng)注冊(cè)Windows類時(shí),設(shè)置WNDCLASS結(jié)構(gòu)中的hbrBackground成員為零)

      在WM_ERASEBKGND消息處理時(shí) 返回非零值

      以上任何一種方法都可以阻止WM_ERASEBKGND 消息去清除窗口。其中,第二個(gè)方案的通??梢砸匀缦麓a實(shí)現(xiàn):

      case WM_ERASEBKGND: return 1;

      當(dāng)你標(biāo)記窗口內(nèi)容無效并試圖更新時(shí),還有如下辦法可以防止WM_ERASEBKGND消息:InvalidateRect函數(shù)的最后一個(gè)參數(shù)可以指明在下一次窗口重畫時(shí),是否窗口的部分背景會(huì)被重刷。將該參數(shù)置為False可以防止當(dāng)窗口需要重畫時(shí)系統(tǒng)發(fā)出WM_ERASEBKGND消息。

      InvalidateRect(hwnd, &rect, FALSE);

      不該畫的時(shí)候一定不要畫 有一個(gè)比較普遍的現(xiàn)象:即使窗口中只有一個(gè)小的部分發(fā)生了改變,往往所有的部分都會(huì)被重畫。比如,經(jīng)常地,當(dāng)窗口大小被改變時(shí),一些(不是所有)的程序會(huì)重畫所有的窗口。通常,這是個(gè)是不必要的,這是因?yàn)楫?dāng)窗口大小被改變時(shí),經(jīng)常是之前窗口的內(nèi)容是不變的,僅僅是改變大小造成的一個(gè)小的邊界區(qū)域需要重畫。此時(shí),沒有必要重畫所有區(qū)域。如果在這里多注意,多考慮,就可以使用好的算法以使得一次只有最小的部分被畫。

      系統(tǒng)中每個(gè)窗口都有更新區(qū)域。這個(gè)區(qū)域描述了窗口中變得無效需要重畫的地方。如果一個(gè)窗口僅僅其需要更新的區(qū)域,不多繪制其他地方,那么窗口的繪制效果將會(huì)非常快。

      有幾種方法可以獲得窗口的更新區(qū)域。通過GetUpdateRgn 函數(shù)可以獲得準(zhǔn)確的更新區(qū)域,這個(gè)函數(shù)返回的結(jié)果可以使矩形的區(qū)域也可以是非矩形的區(qū)域。通過GetUpdateRect 函數(shù)可以獲得需要更新的最小矩形區(qū)域。通常使用矩形的更新區(qū)域比較容易。第三個(gè)方法是在BeginPaint/EndPaint中得到PAINTSTRUCT 結(jié)構(gòu),從而得到準(zhǔn)確的更新區(qū)域信息。

      一個(gè)常規(guī)的畫法函數(shù)是這樣的:

      PAINTSTRUCT ps;HDC hdc;case WM_PAINT: hdc = BeginPaint(hwnd, &ps);// do painting EndPaint(hwnd, &ps);return 0;

      BeginPaint函數(shù)初始化PS(PAINTSTRUCT)結(jié)構(gòu),其中,成員rcPaint是一個(gè)RECT結(jié)構(gòu),描述了包含了需要更新的最小矩形區(qū)域(就像GetWindowRect函數(shù))。如果僅僅在這個(gè)矩形區(qū)域上繪制窗口,速度上繪有很好地提高。

      現(xiàn)在,當(dāng)使用BeginPaint/EndPaint時(shí)Windows會(huì)自動(dòng)剪切掉畫在更新區(qū)域外面的部分。這意味著,你沒有機(jī)會(huì)畫到更新區(qū)域以外的地方??赡苣銜?huì)認(rèn)為,如果是這樣的話,花功夫確保代碼不試圖畫到更新區(qū)域外是沒有意義的,反正沒有畫出任何東西來。然而,你仍然可以避免不必要的API調(diào)用和相關(guān)計(jì)算,所以,我認(rèn)為放一些精力在如何工作地更快上是絕對(duì)值得的。

      如果還是不能解決

      有些時(shí)候,當(dāng)你花了很多努力去考慮非常好的畫法時(shí),發(fā)現(xiàn)窗口還是會(huì)被全部刷新。這通常是由兩個(gè)Window 類的屬性造成的:CS_VREDRAW 和 CS_HREDRAW。如果有其中一個(gè)標(biāo)志被設(shè)置時(shí),那么當(dāng)窗口水平或者豎直方向有大小被改變時(shí),其內(nèi)容每次都會(huì)被重新刷新。所有,你需要關(guān)掉這兩個(gè)標(biāo)志,解決的唯一的方式是在創(chuàng)建窗體和窗體類被注冊(cè)時(shí),確保這兩個(gè)屬性不被設(shè)置。

      WNDCLASSEX wc;wc.cbSize = sizeof(wc);wc.style = 0;/* CS_VREDRAW | CS_HREDRAW;*/...RegisterClassEx(&wc);

      上面的例子描述了當(dāng)窗體類被注冊(cè)時(shí),這兩個(gè)屬性不被設(shè)置的實(shí)現(xiàn)方法。

      有一點(diǎn)需要注意:如果主窗體有了這兩個(gè)屬性,即使子窗體沒有重畫標(biāo)志,會(huì)導(dǎo)致所有子窗體在其大小被改變時(shí)會(huì)被重繪??梢酝ㄟ^以下方式避免這個(gè)情況發(fā)生:

      剪切子窗體

      有時(shí),閃爍的原因是因?yàn)楫?dāng)重畫時(shí),父窗體沒有剪切其子窗體區(qū)域。這樣的結(jié)果導(dǎo)致,整個(gè)父窗口內(nèi)容被重畫,而子窗體又被顯示在了上面(造成閃爍)。這個(gè)可以通過在父窗體上設(shè)置WS_CLIPCHILDREN 來解決。當(dāng)這個(gè)標(biāo)志被設(shè)置時(shí),被子窗體占據(jù)的任何區(qū)域?qū)?huì)被排除在更新區(qū)域外。因此,即使你嘗試在子窗體所在的位置上繪制(父窗口的內(nèi)容),BeginPaint中的剪切區(qū)域也會(huì)阻止其繪制效果。

      雙緩沖和內(nèi)存設(shè)備描述表(Memory Device Context, 簡稱Memory-DC)常見的徹底避免閃爍的方法是使用雙緩沖。其基本的思路是:將窗體的內(nèi)容畫在屏幕外的一個(gè)緩沖區(qū)內(nèi),然后,將該緩沖區(qū)的內(nèi)容再傳遞到屏幕上(使用BilBlt函數(shù))。這是一個(gè)非常好的減少閃爍的方法,但是經(jīng)常被濫用,特別是當(dāng)程序員并不真正地理解如何有效地繪制窗口時(shí)。

      按照我個(gè)人的理解哦,當(dāng)我做五子棋棋盤的時(shí)候,背景色設(shè)置為棕黃色,在制定區(qū)域繪制20X15的小格子作為棋盤。當(dāng)每次點(diǎn)重置時(shí),就是清空棋子時(shí)候,或者更改窗體大小和移動(dòng)窗體時(shí),都會(huì)產(chǎn)生閃爍。為什么這樣子呢?就是當(dāng)窗體重繪的時(shí)候,背景圖畫了一遍,棋盤又畫了一遍,這期間有時(shí)間差,導(dǎo)致很不一致,給人視覺上的閃爍,讓客戶很不舒服,這是程序員需要注意也必須要解決的一個(gè)問題!于是就引進(jìn)了雙緩存技術(shù)。什么是雙緩存呢?它的原理是將所有圖像合成到一起 然后一下顯示出來 移動(dòng)刷新的時(shí)候也是一張一張的往整個(gè)客戶區(qū)覆蓋 這樣就不存在了重疊刷新的問題。如果是控件閃爍.可以利用獲取控件DC繪制在父窗體底部減小色差的方法 應(yīng)用函數(shù)為GetDC()。在我的程序中,個(gè)人認(rèn)為是這樣引用雙緩存的,當(dāng)窗體收到重繪消息時(shí),首先調(diào)用OnEraseBkgnd(CDC* pDC)返回一個(gè)true,將客戶區(qū)的背景色搽除!再調(diào)用onpaint()函數(shù)進(jìn)行重繪,但是在重繪的過程中得注意,利用雙緩存技術(shù)。先獲得一個(gè)繪圖設(shè)備CDC,然后再將圖畫在位圖上,當(dāng)然你重繪的背景也要畫在這個(gè)位圖上~~~最后就是將畫好的位圖按順序的顯示在客戶區(qū)上~~感覺就像跟幻燈片一樣一幅幅的出現(xiàn)吧,并且不讓人的眼球發(fā)覺正在重繪,也沒有閃爍!當(dāng)然,這里面我還碰到一個(gè)問題,就客戶區(qū),重繪區(qū)問題解決了,非客戶區(qū)的問題出現(xiàn)了,非客戶區(qū)的背景是父窗口的顏色,與客戶區(qū)的不一致,當(dāng)把客戶區(qū)擴(kuò)大到整個(gè)窗口的時(shí)候,又會(huì)把非客戶區(qū)的控件覆蓋!解決辦法和原因后面再說~~~ 通常我們編寫雙緩存的代碼的時(shí)候,有經(jīng)典的寫法: HDC hdcMem;HBITMAP hbmMem;HANDLE hOld;PAINTSTRUCT ps;HDC hdc;....case WM_PAINT: // Get DC for window hdc = BeginPaint(hwnd, &ps);// Create an off-screen DC for double-buffering hdcMem = CreateCompatibleDC(hdc);hbmMem = CreateCompatibleBitmap(hdc, win_width, win_height);hOld = SelectObject(hdcMem, hbmMem);// Draw into hdcMem // Transfer the off-screen DC to the screen BitBlt(hdc, 0, 0, win_width, win_height, hdcMem, 0, 0, SRCCOPY);// Free-up the off-screen DC SelectObject(hdcMem, hOld);DeleteObject(hbmMem);DeleteDC(hdcMem);EndPaint(hwnd, &ps);return 0;我的做法是:

      BOOL CGI_PaltFormDlg::OnEraseBkgnd(CDC* pDC){ // TODO: Add your message handler code here and/or call default

      //return CDialog::OnEraseBkgnd(pDC);return true;} void CGI_PaltFormDlg::OnPaint(){ CPaintDC dc(this);// device context for painting SendMessage(WM_ICONERASEBKGND,(WPARAM)dc.GetSafeHdc(), 0);

      // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON);int cyIcon = GetSystemMetrics(SM_CYICON);CRect rect;GetClientRect(&rect);

      dc.FillSolidRect(rect,RGB(255,128,0));

      int x =(rect.Width()cyIcon + 1)/ 2;

      // Draw the icon dc.DrawIcon(x, y, m_hIcon);CDC *pDC=this->GetDC();int red=0,green=0,blue=0;int width=2;

      CDC MenmDC;CBitmap MemBitmap;MenmDC.CreateCompatibleDC(NULL);MemBitmap.CreateCompatibleBitmap(pDC,950,750);

      CBitmap *pOldBit=MenmDC.SelectObject(&MemBitmap);MenmDC.FillSolidRect(0,0,950,750,RGB(255,128,0));

      int tem=0;//畫橫線

      for(int i=0;i<16;i++){ MenmDC.MoveTo(100,100+tem);MenmDC.LineTo(900,100+tem);tem=40+tem;} //畫豎線

      tem=0;for(i=0;i<21;i++){ MenmDC.MoveTo(100+tem,100);MenmDC.LineTo(100+tem,700);tem=40+tem;} pDC->BitBlt(0,0,1400,900,&MenmDC,0,0,SRCCOPY);MemBitmap.DeleteObject();MenmDC.DeleteDC();ReleaseDC(pDC);} 上面是我畫棋盤的語句,只供參考而已!

      二、對(duì)話框背景覆蓋控件問題。

      上面已經(jīng)提及到我遇到的問題。為了達(dá)到兩全其美的效果,竟讓閃屏問題解決了,又讓我的控件不收影響,我想了一個(gè)很笨的辦法!首先確定客戶區(qū)的范圍,我確定的是只雙緩存重繪棋盤部分,矩形區(qū)域?yàn)椋?,0,950,750),這里面我重繪了背景色和棋盤!然后再讓非重繪區(qū)背景色設(shè)置一遍就是和控件一起重繪,說不重繪其實(shí)也是重繪的,只是不一致的重繪而已!

      CPaintDC dc(this);// device context for painting CRect rect;GetClientRect(&rect);dc.FillSolidRect(rect,RGB(255,128,0));當(dāng)然這里面還有個(gè)小問題,就是在onpain()函數(shù)里面最好把對(duì)話框控件和非緩存重繪區(qū)的背景重繪的代碼放在緩存區(qū)重繪代碼的前面,像我上面代碼說的!通過這樣的設(shè)置,我的問題解決了!哈哈,皆大歡喜....

      下載雙緩存解決閃爍及對(duì)話框背景覆蓋控件問題 (WINDOWS API)word格式文檔
      下載雙緩存解決閃爍及對(duì)話框背景覆蓋控件問題 (WINDOWS API).doc
      將本文檔下載到自己電腦,方便修改和收藏,請(qǐng)勿使用迅雷等下載。
      點(diǎn)此處下載文檔

      文檔為doc格式


      聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進(jìn)行舉報(bào),并提供相關(guān)證據(jù),工作人員會(huì)在5個(gè)工作日內(nèi)聯(lián)系你,一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

      相關(guān)范文推薦