程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 第十九章-Delphi自定義部件開發(二)(4)

第十九章-Delphi自定義部件開發(二)(4)

編輯:Delphi

⑵ 定義處理過程類型

一旦你決定產生事件,就要定義事件如何被處理,這就是要決定事件處理過程的類型。在大多數情況下,定義的事件處理過程的類型是簡單的通知類型(TNotifyEvent)和已定義的事件類型。

通知事件只是告訴你特定的事件發生了,而沒有描述什麼時候和什麼地方。通知事件使用時只帶一個TObject類型的參數,該參數是Sender。然而所有通知事件的處理過程都知道是什麼樣的事件發生和發生在那個部件。例如:Click事件是通知類型。當編寫Click事件的處理過程時,你知道的是Click事件發生和哪個部件被點按了。通知事件是單向過程。沒有提供反饋機制。

在某些情況下,只知道什麼事件發生和發生在那個部件是不夠的。如果按鍵事件發生,事件處理過程往往要知道用戶按了哪個鍵。在這種情況下,需要事件處理過程包含有關事件的必要信息的參數。如果事件產生是為了響應消息,那麼傳遞給事件的參數最好是直接來自消息參數。

因為所有事件處理過程都是過程,所以從事件處理過程中返回信息的唯一方法是通過var參數。自定義部件可以用這些信息決定在用戶事件處理過程執行後是否和怎樣處理事件。

例如,所有的擊鍵事件(OnKeyDown、OnKeyUp和OnKeyPressed)通過名為key的var參數傳遞鍵值。為了使應用程序看見包含在事件中的不同的鍵,事件處理過程可以改變key變量值。

⑶ 聲明事件

一旦你決定了事件處理過程的類型,你就要准備聲明事件的方法指針和屬性。為了讓用戶易於理解事件的功能,應當給事件一個有意義的名字,而且還要與部件中相似的屬性的名稱保持一致。

Delphi中所有標准事件的名稱都以“On”開頭。這只是出於方便,編譯器並不強制它。Object Inspector是看屬性類型來決定屬性是否是事件,所有的方法指針屬性都被看作事件,並出現在事件頁中。

⑷ 調用事件

一般說來,最好將調用集中在事件上。就是說在部件中創建一個虛方法來調用用戶的事件處理過程和提供任何缺省處理。當調用事件時,應考慮以下兩點:

● 必須允許空事件

● 用戶能覆蓋缺省處理

不能允許使空事件處理過程產生錯誤的情況出現。就是說,自定義部件的正常功能不能依賴來自用戶事件處理過程的響應。實際上,空事件處理過程應當產生與無事件處理過程一樣的結果。

部件不應當要求用戶以特殊方式使用它們。既然一個空事件處理過程應當與無事件處理過程一樣動作,那麼調用用戶事件處理過程的代碼應當象這樣:

if Assigned(OnClick) then OnClick(Self);

{ 執行缺省處理 }

而不應該有這樣的代碼:

if Assigned(OnClick) then

OnClick(Self)

else

…; { 執行缺省處理 }

對於某些種類的事件,用戶可能想取代缺省處理甚至刪除所有的響應。為支持用戶實現這種功能,你需要傳遞var參數給事件處理過程,並在事件處理過程返回時檢測某個值。空事件處理過程與無事件處理過程有相同作用。因為空事件處理過程不會改變任何var參數值。所以缺省處理總是在調用空事件處理過程後發生。

例如在處理Key-Press事件,用戶可以通過將var參數key的值設置為空字符(#0)來壓制部件的缺省處理,代碼如下:

if Assigned(OnkeyPress) then OnkeyPress(Self key);

if key <> #0 then { 執行缺省處理 } ;

實際的代碼將與這稍有不同,因為它只處理窗口消息,但處理邏輯是相同的。在缺省情況下,部件先調用任何用戶賦予的事件處理過程,然後執行標准處理。如果用戶的事件處理過程將key設為空,則部件跳過缺省處理。

19.2.2.3 處理消息

在傳統Windows編程中,一個很關鍵的方面是處理Windows發送給應用程序的消息。Delphi已經幫你處理了大多數的普通消息,但是在創建部件的過程中有可能Delphi沒有處理方法,得由自己處理消息,也可能創建了新的消息需要處理它們。

學習掌握Delphi的消息處理,要掌握以下三個方面:

● 理解消息處理系統

● 修改(改變)消息處理方法

● 建立新的消息處理方法

1. 理解消息處理系統

所有的Delphi對象內部具有處理消息的機制,如調用消息處理方法或消息處理過程。消息處理的基本思想是對象接收某種消息並派送它們,這是通過調用與接收的消息相應的方法來實現的,如果沒有相應於消息的指定的方法,那就調用缺省處理。下面的圖解表示消息派送系統:

Delphi部件庫定義了將所有Windows消息(包括用戶自定義消息)直接轉換到對象方法調用的消息派送系統。一般沒有必要改變這種消息派送系統,只要建立消息處理方法。

⑴Windows消息中有什麼?

Windows消息是包含若干有用的域的數據記錄。記錄中最重要的是一個整型大小的值,該值標識消息。Windows定義了大量的消息。庫單元Messages聲明了所有消息的標識。消息中其它的有用信息包括兩個域參數和結果域。兩個參數分別是16位和32位的。Windows代碼總是以wParam和lParam來引用它們。

最初,Windows程序員不得不記住包含的每一個參數。現在,微軟公司已經命名了這參數。這樣理解伴隨這些消息的信息就更簡單了。例如,WM_KEYDOWN消息的參數被稱為vkey和keydata,這就比wParam和lParam給出了更多的描述信息。

Delphi為不同類型的消息定義了指定的記錄類型。如鼠標消息在long參數中傳遞鼠標事件的x、y座標,一個在高字,一個在低字。使用鼠標消息記錄,你不需要自己關心哪個字是哪個座標,因為引用這些參數時通過名子Xpos和Ypos取代了lParamLo和lParamHi。

⑵ 派送方法

當應用程序創建窗口時,在Windows Kernel中注冊了一個窗口過程。窗口過程是處理窗口消息的函數。傳統上,窗口過程包括了Case表達式,表達式的每個入口是窗口要處理的每一條消息。當你每次創建窗口時,必須建立完整的窗口過程。

Delphi在下列三方面簡化了消息派送:

● 每個部件繼承了完整的消息派送系統

● 派送系統具有缺省處理。用戶只需定義想響應的消息的處理方法

● 可以修改消息處理的一部分,依靠繼承的方法完成大多數處理

這種消息派送系統的最大優點是用戶能在任何時候安全地發送任何消息給任何部件。如果部件沒有為該消息定義處理方法,那缺省處理方法會解決這個問題,通常是忽略它。

Delphi為應用程序每種類型的部件注冊了名為MainWndProc的方法作為窗口過程。MainWndProc包含了異常處理塊,它完成從Windows到名為WndProc的虛方法傳送消息記錄,並且通過調用應用程序對象的HandleException方法處理異常。

MainWndProc是靜態方法,沒有包含任何消息的指定處理方法。定制過程發生在WndProc中,因為每個部件類型都能覆蓋該方法以適合特定的需要。

WndProc方法為每個影響它們處理的任何條件進行檢查,以捕捉不要的消息。例如,當被拖動時,部件忽略鍵盤事件,因此,TWinControl的WndProc只在沒有拖動時傳送鍵盤事件。最後WndProc調用Dispatch方法,該方法是從TObject繼承來的靜態方法,決定什麼方法來處理消息。

Dispatch使用消息記錄的Msg域來決定怎樣派送特定消息。如果部件已經給該消息定義了處理方法,則Dispatch調用該方法,反之,Dispatch調用缺省處理方法。

2. 改變消息處理方法

在改變自定義部件的消息處理方法之前,先要弄清楚你真正想要做什麼。Delphi將大多數的Windows消息轉換成部件編寫者和部件用戶都能處理的事件。一般來說,你應當改變事件處理行為而不是改變消息處理行為。

為了改變消息處理行為,要覆蓋消息處理方法。也能提供捕獲消息防止部件處理該消息。

⑴ 覆蓋處理方法

為了改變部件處理特定消息的方法,要覆蓋那個消息的處理方法。如果部件不處理該消息,你就需要聲明新的消息處理方法。

為了覆蓋消息處理方法,要在部件中以相同的消息索引聲明新的方法。不要使用override指令,你必須使用Message指令和相應的消息索引。

例如,為了覆蓋一個處理WM_PAINT消息的方法,你要重聲明WMPaint方法:

type

TMyComponent=class(…)

procedure WMPaint(var Message: TWMPaint); message WM_PAINT;

end;

⑵ 使用消息參數

在消息處理方法內部,自定義部件訪問消息記錄的所有參數。因為消息總是var參數,如果需要的話,事件處理過程可以改變參數的值。Result域是經常改變的參數。Result是Windows文檔中所指的消息的返回值:由SendMessage返回。

因為消息處理方法的消息參數的類型隨著被處理的消息的變化而變化,所以應當參考Windows消息文檔中的參數的名字和含義。如果出於某種原因要使用舊風格的消息參數(wParam、lParam),可以配合通用類型TMessage來決定Message。

⑶ 捕獲消息

在某種情況下,你可能希望自定義部件能忽略某種消息。就是說,阻止部件將該消息派送給它的處理方法。為了那樣來捕獲消息,可以覆蓋虛方法WndProc。

WndProc方法在將消息傳給Dispatch方法前屏蔽該消息。它依次決定哪一個方法來處理消息。通過覆蓋WndProc,部件得到了派送消息之前過濾它們的機會。

通常,象下面這樣覆蓋WndProc:

procedure TMyControl.WndProc(var Message: TMessage);

begin

{ 決定是否繼續處理過程 }

inherited WndProc (Message);

end;

下面的代碼是TControl的WndProc的一部分。TControl定義整個范圍內的鼠標消息,當用戶拖動和放置控制時,它們將被濾過。

procedure TControl WndProc(var Message:TMessage);

begin

if (Message.Msg >= WM_MOVSEFIRST) and

(Message.Msg <= WM_MOUSELAST) then

if Dragging then

DragMouseMsg(TWMMOUSE(Message)) { 處理拖動 }

else

… { 正常處理其它 }

… { 否則正常處理 }

end;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved