⑵ 定義處理過程類型
一旦你決定產生事件就要定義事件如何被處理這就是要決定事件處理過程的類型在大多數情況下定義的事件處理過程的類型是簡單的通知類型(TNotifyEvent)和已定義的事件類型
通知事件只是告訴你特定的事件發生了而沒有描述什麼時候和什麼地方通知事件使用時只帶一個TObject類型的參數該參數是Sender然而所有通知事件的處理過程都知道是什麼樣的事件發生和發生在那個部件例如Click事件是通知類型當編寫Click事件的處理過程時你知道的是Click事件發生和哪個部件被點按了通知事件是單向過程沒有提供反饋機制
在某些情況下只知道什麼事件發生和發生在那個部件是不夠的如果按鍵事件發生事件處理過程往往要知道用戶按了哪個鍵在這種情況下需要事件處理過程包含有關事件的必要信息的參數如果事件產生是為了響應消息那麼傳遞給事件的參數最好是直接來自消息參數
因為所有事件處理過程都是過程所以從事件處理過程中返回信息的唯一方法是通過var參數自定義部件可以用這些信息決定在用戶事件處理過程執行後是否和怎樣處理事件
例如所有的擊鍵事件(OnKeyDownOnKeyUp和OnKeyPressed)通過名為key的var參數傳遞鍵值為了使應用程序看見包含在事件中的不同的鍵事件處理過程可以改變key變量值
⑶ 聲明事件
一旦你決定了事件處理過程的類型你就要准備聲明事件的方法指針和屬性為了讓用戶易於理解事件的功能應當給事件一個有意義的名字而且還要與部件中相似的屬性的名稱保持一致
Delphi中所有標准事件的名稱都以On開頭這只是出於方便編譯器並不強制它Object Inspector是看屬性類型來決定屬性是否是事件所有的方法指針屬性都被看作事件並出現在事件頁中
⑷ 調用事件
一般說來最好將調用集中在事件上就是說在部件中創建一個虛方法來調用用戶的事件處理過程和提供任何缺省處理當調用事件時應考慮以下兩點
● 必須允許空事件
● 用戶能覆蓋缺省處理
不能允許使空事件處理過程產生錯誤的情況出現就是說自定義部件的正常功能不能依賴來自用戶事件處理過程的響應實際上空事件處理過程應當產生與無事件處理過程一樣的結果
部件不應當要求用戶以特殊方式使用它們既然一個空事件處理過程應當與無事件處理過程一樣動作那麼調用用戶事件處理過程的代碼應當象這樣
if Assigned(OnClick) then OnClick(Self)
{ 執行缺省處理 }
而不應該有這樣的代碼
if Assigned(OnClick) then
OnClick(Self)
else
… { 執行缺省處理 }
對於某些種類的事件用戶可能想取代缺省處理甚至刪除所有的響應為支持用戶實現這種功能你需要傳遞var參數給事件處理過程並在事件處理過程返回時檢測某個值空事件處理過程與無事件處理過程有相同作用因為空事件處理過程不會改變任何var參數值所以缺省處理總是在調用空事件處理過程後發生
例如在處理KeyPress事件用戶可以通過將var參數key的值設置為空字符(#)來壓制部件的缺省處理代碼如下
if Assigned(OnkeyPress) then OnkeyPress(Self key)
if key <> # then { 執行缺省處理 } ;
實際的代碼將與這稍有不同因為它只處理窗口消息但處理邏輯是相同的在缺省情況下部件先調用任何用戶賦予的事件處理過程然後執行標准處理如果用戶的事件處理過程將key設為空則部件跳過缺省處理
處理消息
在傳統Windows編程中一個很關鍵的方面是處理Windows發送給應用程序的消息Delphi已經幫你處理了大多數的普通消息但是在創建部件的過程中有可能Delphi沒有處理方法得由自己處理消息也可能創建了新的消息需要處理它們
學習掌握Delphi的消息處理要掌握以下三個方面
● 理解消息處理系統
● 修改(改變)消息處理方法
● 建立新的消息處理方法
理解消息處理系統
所有的Delphi對象內部具有處理消息的機制如調用消息處理方法或消息處理過程消息處理的基本思想是對象接收某種消息並派送它們這是通過調用與接收的消息相應的方法來實現的如果沒有相應於消息的指定的方法那就調用缺省處理下面的圖解表示消息派送系統
Delphi部件庫定義了將所有Windows消息(包括用戶自定義消息)直接轉換到對象方法調用的消息派送系統一般沒有必要改變這種消息派送系統只要建立消息處理方法
⑴Windows消息中有什麼?
Windows消息是包含若干有用的域的數據記錄記錄中最重要的是一個整型大小的值該值標識消息Windows定義了大量的消息庫單元Messages聲明了所有消息的標識消息中其它的有用信息包括兩個域參數和結果域兩個參數分別是位和位的Windows代碼總是以wParam和lParam來引用它們
最初Windows程序員不得不記住包含的每一個參數現在微軟公司已經命名了這參數這樣理解伴隨這些消息的信息就更簡單了例如WM_KEYDOWN消息的參數被稱為vkey和keydata這就比wParam和lParam給出了更多的描述信息
Delphi為不同類型的消息定義了指定的記錄類型如鼠標消息在long參數中傳遞鼠標事件的xy座標一個在高字一個在低字使用鼠標消息記錄你不需要自己關心哪個字是哪個座標因為引用這些參數時通過名子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調用缺省處理方法
改變消息處理方法
在改變自定義部件的消息處理方法之前先要弄清楚你真正想要做什麼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消息文檔中的參數的名字和含義如果出於某種原因要使用舊風格的消息參數(wParamlParam)可以配合通用類型TMessage來決定Message
⑶ 捕獲消息
在某種情況下你可能希望自定義部件能忽略某種消息就是說阻止部件將該消息派送給它的處理方法為了那樣來捕獲消息可以覆蓋虛方法WndProc
WndProc方法在將消息傳給Dispatch方法前屏蔽該消息它依次決定哪一個方法來處理消息通過覆蓋WndProc部件得到了派送消息之前過濾它們的機會
通常象下面這樣覆蓋WndProc:
procedure TMyControlWndProc(var Message: TMessage)
begin
{ 決定是否繼續處理過程 }
inherited WndProc (Message)
end;
下面的代碼是TControl的WndProc的一部分TControl定義整個范圍內的鼠標消息當用戶拖動和放置控制時它們將被濾過
procedure TControl WndProc(var Message:TMessage)
begin
if (MessageMsg >= WM_MOVSEFIRST) and
(MessageMsg <= WM_MOUSELAST) then
if Dragging then
DragMouseMsg(TWMMOUSE(Message)) { 處理拖動 }
else
… { 正常處理其它 }
… { 否則正常處理 }
end;
返回目錄DELPHI基礎教程
編輯推薦
Java程序設計培訓視頻教程
JEE高級框架實戰培訓視頻教程
Visual C++音頻/視頻技術開發與實戰
Oracle索引技術
ORACLEG數據庫開發優化指南
Java程序性能優化讓你的Java程序更快更穩定
C嵌入式編程設計模式
Android游戲開發實踐指南
[] [] [] []
From:http://tw.wingwit.com/Article/program/Delphi/201311/25120.html