青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

統計

  • 隨筆 - 50
  • 文章 - 42
  • 評論 - 147
  • 引用 - 0

留言簿(6)

隨筆分類

文章分類

Link

搜索

  •  

積分與排名

  • 積分 - 166566
  • 排名 - 159

最新評論

閱讀排行榜

評論排行榜

OnPaint()函數的作用原理
WM_PAINT是窗口每次重繪都會產生的一個消息。

OnPaint是對這個消息的反應函數

 

mfc 的 CWnd::OnPaint 沒做什么,只是丟給系統處理。

一 :

   先執行OnEraseBkgnd,擦除背景(如果想自繪控件,這個函數直接return TRUE就可以了,這樣就不會擦除背景,不會閃)

 

OnEraseBkGnd與OnPaint的區別與聯系

在OnEraseBkGnd中,如果你不調用原來缺省的OnEraseBkGnd只是重畫背景則不會有閃爍.而在OnPaint里面,由于它隱含的調用了OnEraseBkGnd,而你又沒有處理OnEraseBkGnd 函數,這時就和窗口缺省的背景刷相關了.缺省的 OnEraseBkGnd操作使用窗口的缺省背景刷刷新背景(一般情況下是白刷),而隨后你又自己重畫背景造成屏幕閃動.

OnEraseBkGnd不是每次都會被調用的.如果你調用Invalidate的時候參數為TRUE,那么在OnPaint里面隱含調用BeginPaint的時候就產生WM_ERASEBKGND消息,如果參數是FALSE,則不會重刷背景.

ZYP解釋:void Invalidate( BOOL bErase = TRUE ); 該函數的作用是使整個窗口客戶區無效。窗口的客戶區無效意味著需要重繪,參數bErase為TRUE時,重繪區域內的背景將被重繪即擦除,否則,背景將保持不變。調用Invalidate等函數后窗口不會立即重繪,這是由于WM_PAINT消息的優先級很低,它需要等消息隊列中的其它消息發送完后才能被處理。

OnPaint里面會調用BeginPaint函數自動設置顯示設備內容的剪切區域而排除任何更新區域外的區域更新區域。如果更新區域被標記為可擦除的,BeginPaint發送一個WM_ERASEBKGND消息給窗口。WM_ERASEBKGND消息的響應函數既是OnEraseBkGnd()

所以解決方法有三個半:
1.用OnEraseBkGnd實現,不要調用原來的OnEraseBkGnd函數.
2.用OnPaint實現,同時重載OnEraseBkGnd,其中直接返回.
3.用OnPaint實現,創建窗口時設置背景刷為空
4.用OnPaint實現,但是要求刷新時用Invalidate(FALSE)這樣
的函數.(不過這種情況下,窗口覆蓋等造成的刷新還是要閃一
下,所以不是徹底的解決方法)
都挺簡單的.

在MFC中 任何一個window元件的繪圖 都是放在這兩個member function中
在設定上 OnEraseBkgnd()是用來畫底圖的 而OnPaint()是用來畫主要物件的
舉例說明 一個按鈕是灰色的 上面還有文字
則OnEraseBkgnd()所做的事就是把按鈕畫成灰色
而OnPaint()所做的事 就是畫上文字


既然這兩個member function都是用來畫出元件的
那為何還要分OnPaint() 與 OnEraseBkgnd() 呢
其實OnPaint() 與 OnEraseBkgnd() 特性是有差的
1. OnEraseBkgnd()的要求是快速在裡面的繪圖程式最好是不要太耗時間
因為每當window元件有任何小變動都會馬上呼叫OnEraseBkgnd()
2. OnPaint() 是只有在程式有空閒的時候才會被呼叫
3. OnEraseBkgnd() 是在 OnPaint() 之前呼叫的
所以 OnPaint()被呼叫一次之前 可能會呼叫OnEraseBkgnd()好幾次

如果我們是一個在做圖形化使用者介面的人
常會需要把一張美美的圖片設為我們dialog的底圖
把繪圖的程式碼放在OnPaint() 之中 可能會常碰到一些問題
比方說拖曳一個視窗在我們做的dialog上面一直移動
則dialog會變成灰色 直到動作停止才恢復
這是因為每次需要重繪的時候 程式都會馬上呼叫OnEraseBkgnd()
OnEraseBkgnd()就把dialog畫成灰色
而只有動作停止之後 程式才會呼叫OnPaint() 這時才會把我們要畫的底圖貼上去

這個問題的解法 比較差點的方法是把OnEraseBkgnd() 改寫成不做事的function
如下所示

BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}

以上本來是會呼叫CDialog::OnEraseBkgnd() 但是如果我們不呼叫的話
程式便不會畫上灰色的底色了

Q:基于對話框的程序中如何重載OnEraseBkGnd()函數

A:這是一個消息WM_ERASEBKWND  
  在CLASS   WIZARD中  
  選擇CLASSINFO頁面  
  在MESSAGEFILTER中的選項設在WINDOW就可以看到這個消息了.


比較好的做法是直接將繪圖的程式從OnPaint()移到OnEraseBkgnd()來做
如下所示


// m_bmpBKGND 為一CBitmap物件 且事先早已載入我們的底圖
// 底圖的大小與我們的視窗client大小一致


BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
CRect rc;
GetUpdateRect(&rc);
CDC srcDC;
srcDC.CreateCompatibleDC(pDC);
srcDC.SelectObject(m_bmpBKGND);

pDC->BitBlt(rc.left,rc.top,rc.GetWidth(),
rc.GetHeight(),&srcDC,rc.left,rc.top,SRCCOPY);
return TRUE;
}


特別要注意的是 取得重畫大小是使用GetUpdateRect() 而不是GetClientRect()
如果使用GetClientRect() 會把不該重畫的地方重畫
來自:http://hi.baidu.com/%BF%AA%D0%C4_%D0%D6%B5%DC/blog/item/2f6d3b10b6c622fac2ce79a5.html
   

二 :

     系統的Onpaint中調用了OnDraw,但如果我們自己繼承了一個OnPaint函數又沒有顯式調用OnDraw,則OnDraw就不會被調用,OnInitialUpdate在OnDraw之前,是窗口被創建以后調用的第一個函數。

 

MFC中OnDraw與OnPaint的區別

在OnPaint中調用OnDraw,一般來說,用戶自己的繪圖代碼應放在OnDraw中。

OnPaint()是CWnd的類成員,負責響應WM_PAINT消息。OnDraw()是CVIEW的成員函數,沒有響應消息的功能.當視圖變得無效時(包括大小的改變,移動,被遮蓋等等),Windows發送WM_PAINT消息。該視圖的OnPaint 處理函數通過創建CPaintDC類的DC對象來響應該消息并調用視圖的OnDraw成員函數.OnPaint最后也要調用OnDraw,因此一般在OnDraw函數中進行繪制。


The WM_PAINT message is sent when the UpdateWindow or RedrawWindow member function is called.

在OnPaint中,將調用BeginPaint,用來獲得客戶區的顯示設備環境,并以此調用GDI函數執行繪圖操作。在繪圖操作完成后,將調用EndPaint以釋放顯示設備環境。而OnDraw在BeginPaint與EndPaint間被調用。(一個應用程序除了響應WM_PAINT消息外,不應該調用BeginPaint。每次調用BeginPaint都應該有相應的EndPaint函數。

1) 在mfc結構里OnPaint是CWnd的成員函數. OnDraw是CView的成員函數.
2) OnPaint()調用OnDraw(),OnPrint也會調用OnDraw(),所以OnDraw()是顯示和打印的共同操作。

OnPaint是WM_PAINT消息引發的重繪消息處理函數,在OnPaint中會調用OnDraw來進行繪圖。OnPaint中首先構造一個CPaintDC類得實例,然后一這個實例為參數來調用虛函數OnPrepareDC來進行一些繪制前的一些處理,比設置映射模式,最后調用OnDraw。而
OnDraw和OnPrepareDC不是消息處理函數。所以在不是因為重繪消息所引發的OnPaint導致OnDraw被調用時,比如在OnLButtonDown等消息處理函數中繪圖時,要先自己調用OnPrepareDC。
至于CPaintDC和CClientDC根本是兩回事情 CPaintDC是一個設備環境類,在OnPaint中作為參數傳遞給OnPrepareDC來作設備環境的設置。真正和CClientDC具有可比性的是CWindowDC,他們一個是描述客戶區域,一個是描述整個屏幕。
如果是對CVIEW或從CVIEW類派生的窗口繪圖時應該用OnDraw。

OnDraw()和OnPaint()有什么區別呢?
首先:我們先要明確CView類派生自CWnd類。而OnPaint()是CWnd的類成員,同時負責響應WM_PAINT消息。OnDraw()是CVIEW的成員函數,并且沒有響應消息的功能。這就是為什么你用VC成的程序代碼時,在視圖類只有OnDraw沒有
OnPaint的原因。而在基于對話框的程序中,只有OnPaint。
其次:我們在第《每天跟我學MFC》3的開始部分已經說到了。要想在屏幕上繪圖或顯示圖形,首先需要建立設備環境DC。其實DC是一個數據結構,它包含輸出設備(不單指你17寸的純屏顯示器,還包括打印機之類的輸出設備)的繪圖屬性的描述。MFC提供了CPaintDC類和CWindwoDC類來實時的響應,而CPaintDC支持重畫。當視圖變得無效時(包括大小的改變,移動,被遮蓋等等),Windows 將 WM_PAINT 消息發送給它。該視圖的OnPaint 處理函數通過創建 CPaintDC 類的DC對象來響應該消息并調用視圖的 OnDraw 成員函數。通常我們不必編寫重寫的 OnPaint 處理成員函數。
///CView默認的標準的重畫函數
void CView::OnPaint() //見VIEWCORE.CPP
{

CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc);
//調用了OnDraw
}
///CView默認的標準的OnPrint函數
void CView::OnPrint(CDC* pDC, CPrintInfo*)
{
ASSERT_VALID(pDC);
OnDraw(pDC); // Call Draw
}

既然OnPaint最后也要調用OnDraw,因此我們一般會在OnDraw函數中進行繪制。下面是一個典型的程序。
///視圖中的繪圖代碼首先檢索指向文檔的指針,然后通過DC進行繪圖調用。
void CMyView::OnDraw( CDC* pDC )
{

CMyDoc* pDoc = GetDocument();
CString s = pDoc->GetData();
GetClientRect( &rect ); // Returns a CString CRect rect;
pDC->SetTextAlign( TA_BASELINE | TA_CENTER );
pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() );
}
最后:現在大家明白這哥倆之間的關系了吧。因此我們一般用OnPaint維護窗口的客戶區(例如我們的窗口客戶區加一個背景圖片),用OnDraw維護視圖的客戶區(例如我們通過鼠標在視圖中畫圖)。當然你也可以不按照上面規律來,只要達到目的并且沒有問題,怎么干都成。補充:我們還可以利用Invalidate(),ValidateRgn(),ValidateRect()函數強制的重畫窗口,具體的請參考MSDN吧。

OnDraw中可以繪制用戶區域。OnPaint中只是當窗口無效時重繪不會保留CClientDC繪制的內容。

這兩個函數有區別也有聯系:

1、區別:OnDraw是一個純虛函數,定義為virtual void OnDraw( CDC* pDC ) = 0; 而OnPaint是一個消息響應函數,它響應了WM_PANIT消息,也是是窗口重繪消息。

2、聯系:我們一般在視類中作圖的時候,往往不直接響應WM_PANIT消息,而是重載OnDraw純虛函數,這是因為在CVIEW類中的WM_PANIT消息響應函數中調用了OnDraw函數,如果在CMYVIEW類中響應了WM_PAINT消息,不顯式地調用OnDraw函數的話,是不會在窗口重繪的時候調用OnDraw函數的。

應用程序中幾乎所有的繪圖都在視圖的 OnDraw 成員函數中發生,必須在視圖類中重寫該成員函數。(鼠標繪圖是個特例,這在通過視圖解釋用戶輸入中討論。)


OnDraw 重寫:
通過調用您提供的文檔成員函數獲取數據。
通過調用框架傳遞給 OnDraw 的設備上下文對象的成員函數來顯示數據。
當文檔的數據以某種方式更改后,必須重繪視圖以反映該更改。默認的 OnUpdate 實現使視圖的整個工作區無效。當視圖變得無效時,Windows 將 WM_PAINT 消息發送給它。該視圖的 OnPaint 處理函數通過創建 CPaintDC 類的設備上下文對象來響應該消息并調用視圖的 OnDraw 成員函數。

當沒有添加WM_PAINT消息處理時,窗口重繪時,由OnDraw來進行消息響應...當添加WM_PAINT消息處理時,窗口重繪時,WM_PAINT消息被投遞,由OnPaint來進行消息響應.這時就不能隱式調用OnDraw了.必須顯式調用(
CDC *pDC=GetDC(); OnDraw(pDC); )..
隱式調用:當由OnPaint來進行消息響應時,系統自動調用CView::OnDraw(&pDC).


想象一下,窗口顯示的內容和打印的內容是差不多的,所以,一般情況下,統一由OnDraw來畫。窗口前景需要刷新時,系統會會調用到OnPaint,而OnPaint一般情況下是對DC作一些初始化操作后,調用OnDraw()。


OnEraseBkGnd(),是窗口背景需要刷新時由系統調用的。明顯的一個例子是設置窗口的背景顏色(你可以把這放在OnPaint中去做,但是會使產生閃爍的現象)。

至于怎么界定背景和前景,那要具體問題具體分析了,一般情況下,你還是很容易區別的吧。

的確,OnPaint()用來響應WM_PAINT消息,視類的OnPaint()內部根據是打印還是屏幕繪制分別以不同的參數調用OnDraw()虛函數。所以在OnDraw()里你可以區別對待打印和屏幕繪制。
其實,MFC在進行打印前后還做了很多工作,調用了很多虛函數,比如OnPreparePrint()等。


另外OnInitialUpdate

視圖窗口完全建立后第一個被框架調用的函數。框架在第一次調用OnDraw前會調用OnInitialUpdate,因此OnInitialUpdate是設置滾動視圖的邏輯尺寸和映射模式的最合適的地方。

posted on 2009-08-15 14:56 pear_li 閱讀(1659) 評論(0)  編輯 收藏 引用 所屬分類: C++

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            免费观看成人| 国内精品久久久久久久97牛牛| 亚洲美女av在线播放| 91久久精品一区| 欧美1区2区3区| 另类成人小视频在线| 欧美成人性网| 日韩图片一区| 亚洲欧美日韩久久精品| 欧美在线国产| 老鸭窝91久久精品色噜噜导演| 欧美成人国产一区二区 | 久久综合一区二区三区| 久久久久综合网| 欧美紧缚bdsm在线视频| 国产精品成人观看视频国产奇米| 国产精品美女诱惑| 一区二区三区在线不卡| 夜夜嗨av一区二区三区网站四季av | 久久爱另类一区二区小说| 久久久久在线| 欧美日本不卡高清| 国产精品日韩| 亚洲精品久久久久| 久久精品伊人| 一区二区三区精品国产| 久久久福利视频| 国产精品wwwwww| 亚洲国产一区二区三区在线播 | 99国内精品久久| 久久精品国产v日韩v亚洲 | 国产精品看片你懂得| 国产日韩在线看| 亚洲高清毛片| 亚洲欧美日韩网| 欧美黄色一级视频| 亚洲欧美999| 欧美精品国产一区| 亚洲成色www久久网站| 午夜精品久久久久久久久久久久 | 欧美一区二区视频免费观看| 免费亚洲一区二区| 国产亚洲福利| 亚洲欧美制服另类日韩| 亚洲黄一区二区| 久久精品国产清自在天天线| 欧美日韩亚洲一区三区| 亚洲欧洲综合另类在线| 久久综合中文| 久久精品国产2020观看福利| 国产精品入口66mio| 一区二区三区蜜桃网| 亚洲国产精品一区| 久久综合一区二区| 精品91视频| 另类av一区二区| 久久精品30| 亚洲春色另类小说| 欧美福利在线| 欧美精品v日韩精品v国产精品| 亚洲精品资源| 亚洲区第一页| 欧美日韩在线精品一区二区三区| 日韩午夜在线电影| 日韩一区二区免费看| 欧美日韩在线播放三区| 亚洲欧美激情在线视频| 亚洲欧美日韩一区在线| 国产一区美女| 欧美成人视屏| 欧美精品一区二区三区久久久竹菊| 亚洲精品一区在线观看香蕉| 亚洲精品国产精品国自产观看 | 久久久久久高潮国产精品视| 国产欧美一区二区三区沐欲| 久久国产色av| 久久久久久免费| 亚洲免费观看在线观看| 一本色道久久综合| 国产裸体写真av一区二区| 久久久久久穴| 你懂的亚洲视频| 中文日韩欧美| 亚洲欧美日韩精品久久亚洲区| 欧美伊人久久大香线蕉综合69| 国产欧美日韩视频在线观看| 久久人人97超碰精品888| 久久久亚洲成人| 亚洲精品日产精品乱码不卡| 一区二区三区欧美视频| 国产一区二区三区免费观看| 欧美电影免费观看大全| 欧美日韩视频在线观看一区二区三区 | 亚洲精品女av网站| 亚洲少妇最新在线视频| 精品动漫3d一区二区三区免费版| 亚洲国产欧洲综合997久久| 国产精品v欧美精品v日本精品动漫| 久久精品视频免费播放| 欧美精品一区二区在线观看| 欧美亚洲一区二区在线| 欧美激情国产日韩| 久久天天躁狠狠躁夜夜av| 欧美日本精品在线| 久久久久久久尹人综合网亚洲| 免费成人小视频| 午夜精彩国产免费不卡不顿大片| 久久久国产一区二区三区| 中文国产成人精品| 嫩草国产精品入口| 欧美一站二站| 欧美午夜剧场| 亚洲人成毛片在线播放| 曰韩精品一区二区| 欧美一区二区在线免费观看 | 欧美高清在线视频观看不卡| 国产精品日韩在线观看| 亚洲国产欧美一区二区三区丁香婷| 国产美女精品| 一区二区三区蜜桃网| 亚洲精品一区二区三区在线观看| 亚洲欧美日韩国产中文在线| 一区二区三区www| 欧美激情精品久久久久久久变态| 久久久久久久高潮| 国产伦精品一区二区三区高清| 亚洲福利专区| 亚洲欧洲日韩女同| 玖玖综合伊人| 欧美激情精品久久久久久久变态| 国内视频一区| 久久久久久69| 欧美成人久久| 亚洲国产高清高潮精品美女| 久久精品二区| 免费观看成人鲁鲁鲁鲁鲁视频 | 亚洲激情成人在线| 久久精品视频在线观看| 久久久一本精品99久久精品66| 国产精自产拍久久久久久| 亚洲一区二区三区欧美| 亚洲在线黄色| 国产亚洲欧美日韩在线一区| 亚洲三级免费电影| 在线欧美日韩| 久久久www| 美女视频黄 久久| 激情欧美一区| 老司机aⅴ在线精品导航| 久久嫩草精品久久久久| 亚洲高清网站| 欧美理论电影在线观看| 99re6热只有精品免费观看| 亚洲综合电影| 国产一区二区三区久久| 久久精品首页| 欧美激情在线狂野欧美精品| 亚洲狼人精品一区二区三区| 欧美日韩国产a| 亚洲一区二区伦理| 久久久久久久网| 亚洲国产1区| 欧美日韩免费区域视频在线观看| 日韩网站免费观看| 久久九九全国免费精品观看| 亚洲人成在线观看| 国产精品一级久久久| 免费成人网www| 亚洲婷婷综合久久一本伊一区| 久久久久久久久一区二区| 999亚洲国产精| 国产综合色在线| 欧美日韩ab片| 久久久久久久久久码影片| 日韩一区二区免费高清| 久久综合婷婷| 亚洲一区二区少妇| 亚洲黄色av| 国产亚洲欧美日韩一区二区| 欧美人妖在线观看| 久久伊人一区二区| 亚洲男人影院| 99re这里只有精品6| 免费在线观看日韩欧美| 午夜精品国产精品大乳美女| 亚洲精品久久久久久一区二区| 国产精品国产三级国产普通话三级 | 亚洲成色www8888| 国产精品视频男人的天堂| 欧美激情精品久久久六区热门 | 亚洲第一黄色| 国产精品久久97| 免费在线看成人av| 久久国产色av| 亚洲欧美国产77777| 99国产精品国产精品久久| 亚洲国产成人在线视频| 久久一区二区三区四区五区| 午夜视频在线观看一区二区三区| 亚洲精品一线二线三线无人区|