delphi VCL研究之消息分发机制(转)
原文來(lái)源,http://blog.csdn.net/sushengmiyan/article/details/8635550
1.VCL 概貌
先看一下VCL類圖的主要分支,如圖4.1所示。
在圖中可以看到,TObject是VCL的祖先類,這也是Object Pascal語(yǔ)言所規(guī)定的。但實(shí)際上,TObject以及TObject聲明所在的system.pas整個(gè)單元,包括在“編譯器魔法”話題中提到的_ClassCreate等函數(shù),都是編譯器內(nèi)置支持的。因此,無(wú)法修改、刪除system.pas中的任何東西,也無(wú)法將system.pas加入你的project,否則會(huì)得到“Identifier redeclared ‘system’”的錯(cuò)誤提示,因project中已經(jīng)被編譯器自動(dòng)包含了system單元。
意思是,TObject是Object Pascal語(yǔ)言/編譯器本身的一個(gè)性質(zhì)!
TObject封裝了Object Pascal類/對(duì)象的最基本行為。
TPersistent派生自TObject,TPersistent使得自身及其派生類對(duì)象具有自我保存、持久存在的能力。
TComponent派生自TPersistent,這條分支之下所有的類都可以被稱為“組件”。組件的一般特性是:
(1)可出現(xiàn)在開(kāi)發(fā)環(huán)境的“組件板”上。
(2)能夠擁有和管理其他組件。
(3)能夠存取自身(這是因?yàn)門(mén)Component派生自TPersistent)。
TControl派生自TComponent,其分支之下所有的類,都是在運(yùn)行時(shí)可見(jiàn)的組件。
TWinControl派生自TControl,這個(gè)分支封裝了Windows系統(tǒng)的屏幕對(duì)象,也就是一個(gè)真正的Windows窗口(擁有窗口句柄)。
TCustomControl派生自TwinControl。從TCustomControl開(kāi)始,組件擁有了Canvas(畫(huà)布)屬性。
2.TObject與消息分發(fā)
首先來(lái)看一下TObject這個(gè)“萬(wàn)物之源”究竟長(zhǎng)得何等模樣。它的聲明如下:
1 TObject = class 2 constructor Create; 3 procedure Free; 4 class function InitInstance(Instance: Pointer): TObject; 5 procedure CleanupInstance; 6 function ClassType: TClass; 7 class function ClassName: ShortString; 8 class function ClassNameIs(const Name: string): Boolean; 9 class function ClassParent: TClass; 10 class function ClassInfo: Pointer; 11 class function InstanceSize: Longint; 12 class function InheritsFrom(AClass: TClass): Boolean; 13 class function MethodAddress(const Name: ShortString): Pointer; 14 class function MethodName(Address: Pointer): ShortString; 15 function FieldAddress(const Name: ShortString): Pointer; 16 function GetInterface(const IID: TGUID; out Obj): Boolean; 17 class function GetInterfaceEntry(const IID: TGUID): PInterfaceEntry; 18 class function GetInterfaceTable: PInterfaceTable; 19 function SafeCallException(ExceptObject: TObject; 20 ExceptAddr: Pointer): HResult; virtual; 21 procedure AfterConstruction; virtual; 22 procedure BeforeDestruction; virtual; 23 procedure Dispatch(var Message); virtual; 24 procedure DefaultHandler(var Message); virtual; 25 class function NewInstance: TObject; virtual; 26 procedure FreeInstance; virtual; 27 destructor Destroy; virtual; 28 end; Delphi Code? ? ? ?從TObject的聲明中可以看到,TObject包含了諸如實(shí)例初始化、實(shí)例析構(gòu)、RTTI、消息分發(fā)等相關(guān)實(shí)現(xiàn)的方法。現(xiàn)在就來(lái)研究一下TObject與消息分發(fā),這也是VCL對(duì)Windows消息封裝的模型基礎(chǔ)。
? ? ? 在TObject類中,有一個(gè)Dispatch()方法和一個(gè)DefaultHandler()方法,它們都是與消息分發(fā)機(jī)制相關(guān)的。
Dispatch()負(fù)責(zé)將特定的消息分發(fā)給合適的消息處理函數(shù)。首先它會(huì)在對(duì)象本身類型的類中尋找該消息的處理函數(shù),如果找到,則調(diào)用它;如果沒(méi)有找到而該類覆蓋了TObject的DefaultHandler(),則調(diào)用該類的DefaultHandler();如果兩者都不存在,則繼續(xù)在其基類中尋找,直至尋找到TObject這一層,而TObject已經(jīng)提供了默認(rèn)的DefaultHandler()方法。
? ? ? 先來(lái)看一個(gè)示例程序,它演示了消息分發(fā)及處理的過(guò)程。
首先自定義一個(gè)消息結(jié)構(gòu)TMyMsg,它是我們自定義的消息記錄類型。對(duì)于自定義的消息類型,VCL只規(guī)定它的首4字節(jié)必須是消息編號(hào),其后的數(shù)據(jù)類型任意。同時(shí),VCL也提供了一個(gè)TMessage類型用于傳遞消息。在此程序中,不使用TMessage,而用TMyMsg代替:
TMyMsg記錄類型的第2個(gè)域我們定義為MsgText,由該域的字符串來(lái)給出對(duì)這個(gè)消息的具體描述信息。當(dāng)然,這些信息都是由消息分發(fā)者給出的。
然后,定義一個(gè)類,由它接受外界發(fā)送給它的消息。這個(gè)類可以說(shuō)明這個(gè)演示程序的核心問(wèn)題。
在Object Pascal中,指明類的某個(gè)方法為某一特定消息的處理函數(shù),則在其后面添加message關(guān)鍵字與消息值,以此來(lái)通知編譯器。正如上面類定義中的
procedure AcceptMsg2000(var msg : TMyMsg); message 2000;指明AcceptMsg2000()方法用來(lái)處理值為2000的消息,該消息以及參數(shù)將通過(guò)msg參數(shù)傳遞給處理函數(shù)。
TMsgAccepter類除提供了值為2000和2002的兩個(gè)消息的處理函數(shù)外,還提供了一個(gè)默認(rèn)的消息處理方法DefaultHandler()。該方法是在TObject中定義的虛方法,而在TMsgAccepter類中覆蓋(override)了該方法,重新給出了新的實(shí)現(xiàn)。
TMyMsg結(jié)構(gòu)聲明與TMsgAccepter類的聲明與實(shí)現(xiàn)都被定義在MsgDispTest單元中。完整的單元代碼如下,請(qǐng)參看其中的TMsgAccepter類的各方法的實(shí)現(xiàn):
接著就是界面代碼,我們?cè)贏pplication的主Form(Form1)上放入3個(gè)按鈕,程序界面如圖4.2所示。
界面上的3個(gè)按鈕的名字分別是:btnMsg2000、btnMsg2001、btnMsg2002。該3個(gè)按鈕用來(lái)分發(fā)3個(gè)消息,將3個(gè)消息的值分別定義為2000、2001和2002。
在Form的OnCreate事件中,創(chuàng)建一個(gè)TMsgAccepter類的實(shí)例。然后,在3個(gè)按鈕的OnClick事件中分別加上代碼,將3個(gè)不同的消息分發(fā)給TMsgAccepter類的實(shí)例對(duì)象,以觀察TMsgAccepter作出的反應(yīng)。最后,在Form的OnDestroy事件中,析構(gòu)TMsgAccepter類的實(shí)例對(duì)象。完整的界面程序單元代碼如下:
在TMsgAccepter類的代碼中可以看到,它只能處理編號(hào)為2000和2002的消息,而沒(méi)有編號(hào)為2001的消息的處理函數(shù),但它覆蓋了TObject的DefaultHandler(),于是就提供了默認(rèn)的消息處理函數(shù)。
運(yùn)行程序,分別單擊3個(gè)按鈕,得到了3句不同的回答。對(duì)于消息2000和2002,TMsgAccepter照單全收,正確識(shí)別出所接收到的消息。而只有在接收消息2001時(shí),由于沒(méi)有提供專門(mén)的消息處理函數(shù),導(dǎo)致了對(duì)DefaultHandler()的調(diào)用。幸運(yùn)的是,在DefaultHandler中,還可以使用message參數(shù)給出的附加信息(TMyMsg記錄類型中的MsgText域)。
轉(zhuǎn)載于:https://www.cnblogs.com/jiqiwoniu/p/4552289.html
總結(jié)
以上是生活随笔為你收集整理的delphi VCL研究之消息分发机制(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Jquery Mobile 百度地图 D
- 下一篇: 1724: [Usaco2006 Nov