很多人認為Delphi是一個RAD工具,包括我自己在上學的時候對Delphi也有偏見,現在走出了“象牙塔”,涉及的面廣了,遇到的問題多了,慢慢地也有了自己的一點心得體會。其實,Delphi是基於Object Pascal 語言的開發工具,也就是說Delphi本質上是一種語言工具,而且是真正的物件導向的。下面我舉的例子就是用Delphi實作的一個托盤小程式。程序短小精悍,脈絡分明,我將對關鍵部分進行詳細講解。就像候俊傑先生把MFC一層一層地剝開一樣,今天我也來一次「庖丁解牛」。
在Delphi中涉及到系統程式設計的方面毫無例外都要呼叫API函數,在ShellAPI.pas單元中有要用到的API函數的原型。
實戰演練:
一.新建一個應用程式:File->New Applicaton 在Interface部分定義一個訊息常數:const WM_NID=WM_USER+1000; 系統規定從WM_USER開始為使用者自訂訊息。
二.定義一個全域變數: NotifyIcon:TNotifyIconData,NotifyIcon是非常重要的一個變量,整個程式基本上就是圍繞著這個變數在轉。 TNotifyIconData是記錄類型,按住Ctrl鍵,在TNotifyIconData 雙擊即進入ShellAPI.pas單元。 (註:在Delphi中,這是一個非常好的對原始程式碼進行分析的方法,原始碼說明一切,你要想知道程式背後的內幕,最好的方法就是分析原始程式碼!)此時出現了以下賦值語句:
TNotifyIconData = TNotifyIconDataA,這個意思很明顯,就是說TNotifyIconData和TNotifyIconDataA是同種資料型,接著往下看有:
TNotifyIconDataA = _NOTIFYICONDATAA,意思與剛才的一樣,再往下看:
type
_NOTIFYICONDATAA = record
cbSize: DWord;
Wnd: HWND;
uID: UINT;
uFlags: UINT;
uCallbackMessage: UINT;
hIcon: HICON;
szTip: array [0..63] of AnsiChar;
end;
這真是「千呼萬喚始出來,猶抱琵琶半遮面」。現在大家很清楚了,我們剛剛定義的全域變數NotifyIcon其實是一個包含有7個成分的記錄類型變量,就相當於C/C++中的結構體變數(C/C++的程式設計師應該是再熟悉不過了)。下面我們逐一來解釋記錄類型中的7個部分各有什麼功能。
1> cbSize就是你定義的NotifyIcon變數的大小,用SizeOf(TNotifyIconData)可以取得,如果你是個熟練的C/C++程式設計師,你應該不會陌生。在C/C++中,每當要為一個結構體變數分配記憶體的時候都要:透過SizeOf(Struct type) 來獲知存放一個這樣的結構體變數要多少記憶體。
2> Wnd是句柄,你希望托盤程式產生的訊息有哪個窗體來處理就讓Wnd指向那個窗體。
例如:你準備在工作列的托盤小圖示上點擊時窗體是窗體在「顯示」和「隱藏」之間切換,則把Wnd指向主窗體。
3> uID:如果你要建立多個托盤小程序,那麼要怎麼區分它們呢?就是靠這個ID號碼來區分。
3> uFlags是一個標誌位,它表示目前所建立的托盤程式具有哪些性質:
NIF_ICON 表示目前所設定的圖示(即hIcon的值)是有效的
NIF_MESSAGE 表示目前所設定的系統訊息(即uCallBackMessage的值)是有效的
NIF_TIP 表示目前所設定的提示條(即szTip的值)是有效的。
4> uCallBackMessage這是7個部分裡面最重要的一個。這裡指定一個回調訊息,也就是說這裡定義一個訊息名,當你點擊或右鍵點擊托盤圖示的時候就會向你在Wnd所指向的窗體發送一個在uCallBackMessage中定義的訊息名,然後你在程式中定義一個訊息出來函數來處理這個訊息。這樣就把Windows關於訊息的整套流程都處理好了。
6> hIcon為托盤圖示的句柄,根據這個句柄你就可以增加、修改、刪除圖示。
7> szTip就是當你的滑鼠放到工作列托盤的小圖示上的時候彈出來的提示訊息。
這裡我花了大量的筆墨介紹TNotifyIconData的內幕,把這部分搞清楚了,後面的東西就順理成章了。
三. 雙擊主窗體,進入FormCreate的程式碼區域:
TForm1.FormCreate(Sender:TObject);
Begin
//NotifyIcon為全域變量,在程式的開頭已經定義了
with NotifyIcon do
begin
cbSize:=SizeOf(TNotifyIconData);
Wnd:=Handle; //指向目前窗體Form1的句柄
uID:=1;
uFlags:=NIM_ICON 或 NIM_MESSAGE or NIM_TIP;
uCallBackMessage:=WM_NID;
hIcon:=application.Icon.Handle;
szTip:=”張家惡少”;
end;.
//把設定好的變數NotifyIcon加入到系統中以便處理
Shell_NotifyIcon(NIM_ADD,@NotifyIcon);
End;
四.接下來就是定義一個訊息處理函數:系統給了窗體一個訊息,就由下面這個函數來處理。每個訊息處理函數都是處理某一類訊息的,大家仔細地看看下面函數體的定義和一般的函數定義有什麼不一樣:訊息處理函數要在後面加上訊息的名稱,這樣當系統發來WM_NID訊息時,就是自動觸發WMNID訊息處理函數。
PRocedure WMNID(var msg:TMessage);message WM_NID;
begin
case msg.LParam of
WM_LBUTTONUp; Form1.Visible:=not Form1.Visible;
WM_RBUTTONUP: ShowMessage('您點選的是右鍵');
End;
End;
好了,一個最簡單的程式誕生了,大家自己設定好自己喜歡的圖示.
Project->Options,選取Application頁面,在Icon項目中載入自己喜歡的圖標,這樣程式執行時,在工作列裡顯示的就是你喜歡的圖標了。當你點擊圖示時,窗體Form1會在可見與不可見之間切換,也就是說點擊一下顯示,再點擊一下又隱藏。當你右鍵點擊圖示的時候會彈出訊息:「你點擊的是右鍵」。
五.最後要記住在關閉應用程式的時候要釋放掉建立的托盤程序,否則會佔用系統資源。
TForm1.FormDestroy(Sender:TObject);
Begin
Shell_NotifyIcon(NIM_DELETE,@NotifyIcon);
End;
畢業快半年了,很多東西在學校總理解不了,認識不夠深刻;出到社會,接觸了不少道中朋友,受益非淺,每有心得體會,總想寫成文字,一來總結自己學的東西,二來和大家共同交流。
E_Mail: [email protected] QQ: 8133413 張家惡少