C#中控件Control的Paint事件和OnPaint虚函数的区别
句柄?:?句柄,是整個Windows編程的基礎。一個句柄是指使用的一個唯一的整數(shù)值,即一個4字節(jié)(64位程序中為8字節(jié))長的數(shù)值,來標識應用程序中的不同對象和同類對象中的不同的實例,諸如,一個窗口,按鈕,圖標,滾動條,輸出設備,控件或者文件等。應用程序能夠通過句柄訪問相應的對象的信息,但是句柄。
????重寫?:?當一個子類繼承一父類,而子類中的方法與父類中的方法的名稱,參數(shù)個數(shù)、類型都完全一致時,就稱子類中的這個方法重寫了父類中的方法。
????函數(shù)?:?函數(shù)(function),最早由中國清朝數(shù)學家李善蘭翻譯,出于其著作《代數(shù)學》。之所以這么翻譯,他給出的原因是“凡此變數(shù)中函彼變數(shù)者,則此為彼之函數(shù)”,也即函數(shù)指一個量隨著另一個量的變化而變化,或者說一個量中包含另一個量。
????代碼?:?代碼就是程序員用開發(fā)工具所支持的語言寫出來的源文件,是一組由字符、符號或信號碼元以離散形式表示信息的明確的規(guī)則體系。代碼設計的原則包括惟一確定性、標準化和通用性、可擴充性與穩(wěn)定性、便于識別與記憶、力求短小與格式統(tǒng)一以及容易修改等。 源代碼是代碼的分支,某種意義上來說。
兩種方法是有區(qū)別的:
用Paint事件繪制窗體(如在窗體繪制橢圓)時,會被基類OnPaint虛方法所調用,而重寫OnPaint方法繪制窗體時則通過調用代碼base.OnPaint(e);調用基類的虛方法,從而間接調用基類預先定義好的Paint事件。
OnPaint虛方法的主要代碼原形應該類似以下形式(從中便可以看出):
protected virtual OnPaint(PaintEventArgs e) { if(paint != null) { paint(this,e); } }如果直接重寫OnPaint虛函數(shù),Paint事件就會失效。但是如果下面這樣重寫Paint事件就不會失效:
代碼如下: protected override OnPaint(PaintEventArgs e) { base.OnPaint(e); //自己的代碼 }(一)重繪時候經常會用到OnPaint()和Paint,它們有什么區(qū)別呢?
1.OnPaint方法是對一個控件來說的;而Paint事件是對一個控件對象來說的。它們中前者相當于是類的一個成員函數(shù),而后者相當于是類的一個函數(shù)指針類型的變量(會因對象的不同而不同)。????
2.OnPaint方法引發(fā)Paint事件,所以重寫OnPaint方法,一定要調用base.OnPaint,否則就不會引發(fā)Paint事件了。OnPaint原形應該類似以下形式(從中便可以看出):
3.從實例中觀察二者調用順序
代碼如下: private void Form1_Paint(object sender, PaintEventArgs e){test t = new test();t.AntiAlias = true;t.SetColor(test.eShapeColor.Circle1FillColor, Color.DarkCyan);e.Graphics.DrawImageUnscaled(t.Image, 10, 10);}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);//引發(fā)Paint事件處理(處理該事件時候調用Form1_Paint方法) ..........}Form1_Paint()只是處理Paint事件的方法,也可將它的四行代碼在OnPaint方法中寫,此時可以不寫base.OnPaint(e),即不引發(fā)事件處理,也可達到同樣的效果。
(二)那么應分別在什么情況下使用它們呢??
1.如果想對所有控件都按照某種固定的方式顯示,如:自己寫控件時,則需要修改重載控件的OnPaint方法;而如果僅僅在某個環(huán)境下,對某個對象要做不同的顯示,則只需在其的Paint事件中做即可。
2.在實現(xiàn)派生類的時候,遵循 C# 原則35:選擇重寫函數(shù)而不是使用事件句柄。
許多.net類庫中的類都提供了兩種不同的處理事件句柄的方法。既可以為其添加事件,也可以重寫其基類的事件抽象方法。在實現(xiàn)派生類的時候,更好的選擇是重寫基類中的抽象方法。
因為這樣,一旦事件句柄拋出異常,不會再有其他的事件句柄被調用。這避免了一些錯誤代碼繼續(xù)被調用而引發(fā)的問題。通過重寫受保護的虛方法,我們的句柄可以 第一個被調用?;愔刑摵瘮?shù)負責其他相關句柄的調用。這意味著如果需要調用那些事件句柄(一般來說是需要的),就要調用基類的虛函數(shù)。在有些特殊情況下我 們需要替換基類的默認行為,可能不需要調用任何原有的事件句柄。雖然我們不能保證所有的事件句柄都被執(zhí)行,因為其可能會拋出異常,但是我們可以保證派生類 的行為是正確的。
使用override比添加事件句柄高效的多。在 條款 22中展示了System.Windows.Forms.Control類是如何存儲句柄時間并將其對應到每一個事件的。這種事件機制由于要檢查事件句柄將造成更多的消耗。事件句柄列表中的每個方法都需要執(zhí)行。相比重寫虛方法,通過事件處理會消耗更多的時間。
此外,重寫虛方法只需要維護一個函數(shù)就可以達到檢查和修改的目的,代碼更清晰。而事件機制需要兩個維護點:事件句柄函數(shù)和事件綁定代碼。其中任何一點都可能造成整體功能上的失敗。一個函數(shù)顯然要簡單些。
總結:
OnPaint是Control類中的方法,Paint是事件,Paint是用于改變部分顯示用比較合適,實際上Paint事件在OnPaint中被調用,如果你重寫OnPaint但是不調用base.OnPaint(e);的話Paint事件就失效了,所以對于自定義控件而言要改變外觀重寫OnPaint更合適,一般情況下繪制圖形編寫Paint事件的處理方法就行。
小提示:
1、做小游戲的話,用PictureBox代替Panel做繪圖板面比較合適,因為默認雙緩沖,不容易閃。
2、Control.Refresh??Control.Invalidate?和?Control.OnPaint之間的聯(lián)系和區(qū)別:
1)、Control.Invalidate會放一個WM_PAINT消息到消息隊列,當Control處理到該消息的時候,就調用OnPaint。
2)、Control.Refresh相當于以下兩行:
Control.Invalidate(true);
Control.Update();
3)、Control.Update會搜索消息隊列,如果找到WM_PAINT,就把它取出,'直接'調用OnPaint。
因此,Invalidate告訴系統(tǒng)當前窗口要求重畫,但不要求立即執(zhí)行,那些排在WM_PAINT前面的消息會先處理。
Refresh則立刻重畫窗口。
總結
以上是生活随笔為你收集整理的C#中控件Control的Paint事件和OnPaint虚函数的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宏块帧内预测的具体过程
- 下一篇: linux 可执行文件的分析(gcc G