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...