Delphi對於控制項的SuperClassing

2021-04-02 01:46:53 字數 4427 閱讀 8277

windows

內部預定義了一些通用的控制項,我們在用這些控制項的時候不必再呼叫

registerclass

註冊乙個視窗類,只要直接呼叫

createwindows

,並指定乙個預定義的視窗類就可以,比如,我們要建立乙個

button

,只要用如下形式即可:

createwindows(.., 『button』,...)。但用

delphi

寫出來的程式,用

spy看它的某個控制項的視窗類名,卻是這個控制項類的

classname

,比如,乙個按鈕控制項,它的視窗類名是

tbutton

,tbutton

控制項也是封裝系統預定義的

button

控制項,按理它的視窗類名應該是

button

才對啊,怎麼會變成

tbutton

呢。這個問題長期困擾著我。

昨晚看了一下《

window 95

程式設計指南》,其中講到了

superclassing

的技術,可以以系統標準控制項為基礎,設計新的控制項。這個技術使我恍然大悟,趕緊看了一下

vcl的**,果然是用了這樣的技術,大喜,以此文記之。

我以乙個

tbutton

控制項的建立過程,說明

superclassing

技術在delphi

控制項建立的應用。

tbutton

建立視窗是在

createwnd

方法開始,下面是建立的乙個大概流程:

tbutton.createwnd;

| twincontrol.createwnd;

| | tbutton.createparams(var params: tcreateparams);

| | | tbuttoncontrol.createparams(var params: tcreateparams);

| | | | twincontrol.createparams(var params: tcreateparams);

| | | twincontrol.createsubclass(var params: tcreateparams;

| | |controlclassname: pchar);

| | windows.registerclass(windowclass)

| | twincontrol.createwindowhandle(const params: tcreateparams);

在twincontrol.createparams(var params: tcreateparams)

中設定了視窗的一些基本的風格,其中有一句重要,是:

with params do

begin

...strpcopy(winclassname, classname);

...end;

裡面的winclassname

即是視窗類名,這時被賦為控制項的類名,即是

tbutton

。tbutton

覆蓋createparams

,作一些自己的風格設定,其中呼叫到

twincontrol

的createsubclass

,是這樣呼叫的:

createsubclass(params, 'button');

button

就是系統的預定義按鈕控制項的視窗類名。那麼這個方法有什麼作用呢,它在裡面呼叫了數個

getclassinfo

函式,以獲得該視窗類的類風格,類風格填充到

params

引數的windowclass

結構成員中。這時

windowclass

這個結構就有了

button

標準視窗的類風格的資料了。

設定完視窗類的風格後,回到

twincontrol

的createwnd

方法,開啟這個方法的**來看,有一句非常重要:

fdefwndproc := windowclass.lpfnwndproc;

因為我們前面已經呼叫了

createsubclass

獲得了button

的視窗類的類風格,並填充在

params

引數的windowclass

結構中。所以上面我們看到的這一句是將

button

的視窗過程儲存到

fdefwndproc

這個函式指標裡面,它是

twincontrol

的乙個成員,請記住這個成員。

接下來呼叫:

classregistered := getclassinfo(windowclass.hinstance, winclassname, tempclass);

還記得winclassname

嗎,是它是

params

的成員,在上面它已經被為

』tbutton』

了。檢查有這個名字的視窗類是否已經被註冊了,如果沒有則有下面三句非常重要的**:

windowclass.lpfnwndproc := @initwndproc;

windowclass.lpszclassname := winclassname;

if windows.registerclass(windowclass) = 0 then raiselastoserror;

首先將button

視窗的視窗過程設定為

initwndproc

。再將它的視窗類名字設定為

winclassname

也即是tbutton

。最後註冊視窗類。

好了視窗類註冊完了,就呼叫以下兩句:

createwindowhandle(params);

createwindowhandle

根據params

裡面的引數建立視窗,**比較簡單。

這乙個tbutton

的建立過程就完了,那麼它是如何享有系統預定義的

button

的那些功能的呢。接著往下看。

當在createwindowhandle

裡面呼叫

createwindow

函式時,系統直接傳送乙個

wm_create

訊息給這個新建的視窗。而上面我們已經知道這個視窗的視窗函式就是

initwndproc

。在它裡面呼叫了:

setwindowlong(hwindow, gwl_wndproc,

longint(creationcontrol.fobjectinstance));

將視窗過程重新指定,關於這個技術李維的《

inside vcl

》已經有說明。返正視窗過程最後就到了

twincontrol

的wndproc

這個方法去了,以後所有的訊息將由這個方法來處理。

那就看看這個方法吧:

twincontrol.wndproc

這個方法沒有看到什麼資訊,不過它會呼叫父類的

wndproc

,再看看

tcontrol.wndproc;

裡面最終呼叫了

tobject

的dispatch(message)

,將訊息通過

dmt傳送到對應的訊息處理方法中,最後還會呼叫

tobject

的defaulthandler

。tcontorl

覆蓋了這個方法,而

twincontrol

也覆蓋了這個方法。不過

tcontrol

沒有我們要的資訊。關鍵就是

twincontrol

的defaulthandle

。在裡面終於找到最最重要的這一句:

result := callwindowproc(fdefwndproc, fhandle, msg, wparam, lparam);

還記得fdefwndproc

嗎,在上面,它被指向了

button

類的原始視窗過程。這裡呼叫了它,亦即

windows

在內部會自動對

tbutton

的一些button

特性進行處理。

至此superclassing

完成。而我們也看到

button

控制項變成了

tbutton

控制項。呵呵,如果看一下那本《

window 95

程式設計指南》,再看一下

vcl原始碼,相信會理解得更清楚。

delphi 控制項簡介

一 codegear interbase express 自帶的資料庫 dataset mybase dataaccess 伺服器遠端資料 data snap connection 遠端資料庫 dbexpress delphi 自己連線 db2,informix,interbase,mssql,my...

Delphi 控制項安裝

delphi 控制項安裝 比較全 由於元件提供的方式不同,所以安裝的方法也是不一樣的,下面就目前常見的各種形式的元件的安裝方法介紹一下。1只有乙個dcu檔案的元件。dcu檔案是編譯好的單元檔案,這樣的元件是作者不想把原始碼公布。一般來說,作者必須說明此元件適合delphi的哪種版本,如果版本不對,在...

Delphi遍歷控制項

var i integer begin for i 0 to panel1.controlcount do begin 控制項 panel1.controls i 加入自己 end end procedure tform1.button2click sender tobject var i inte...