DELPHI中的消息處理機制
發(fā)表時間:2024-02-16 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]Delphi 是Borland 公 司 提 供 的 一 種 全 新 的WINDOWS 編 程 開 發(fā) 工 具. 由 于 它 采 用 了 具 有 彈 性 的 和 可 重 用 的 面 向 對 象Pascal(object-oriented pascal) 語 言, 并 有 強 大 的 數(shù) 據(jù) 庫 引 ...
Delphi 是Borland 公 司 提 供 的 一 種 全 新 的WINDOWS 編 程 開 發(fā) 工 具. 由 于 它 采 用 了 具 有 彈 性 的 和 可 重 用 的 面 向 對 象Pascal(object-oriented pascal) 語 言, 并 有 強 大 的 數(shù) 據(jù) 庫 引 擎(BDE), 快 速 的 代 碼 編 譯 器, 同 時 又 提 供 了 眾 多 出 色 的 構(gòu) 件. 受 到 廣 大 編 程 人 員 的 青 睞. 在 眾 多 的 編 程 語 言( 如VB,PowerBuilder,Powerpoint 等) 中 脫 穎 而 出. 其 中 一 個DELPHI 強 于 其 他 編 程 語 言( 如VB4.0) 的 地 方 就 是 在DELPHI 中 可 自 定 義 消 息, 并 可 直 接 處 理 消 息. 這 對 于 那 些 希 望 編 寫 自 己 的 構(gòu) 件(Component), 或 者 希 望 截 獲. 過 濾 消 息 的 用 戶 來 說 是 必 不 可 少 的. 因 為 編 寫 構(gòu) 件 一 般 要 對 相 應(yīng) 的 消 息 進 行 處 理. 下 面 就 對Delphi 中 消 息 處 理 機 制 進 行 一 下 介 紹。
一.DELPHI VCL 中 消 息 的 傳 遞
Delphi 中 每 一 個VCL(Visual Component Library) 構(gòu) 件( 如Tbutton,Tedit 等) 都 有 一 內(nèi) 在 的 消 息 處 理 機 制, 其 基 本 點 就 是 構(gòu) 件 類 接 收 到 某 些 消 息 并 把 它 們 發(fā) 送 給 適 當 的 處 理 方 法, 如 果 沒 有 特 定 的 處 理 方 法, 則 調(diào) 用 缺 省 的 消 息 處 理 句 柄。
其 中mainwndproc 是 定 義 在Twincontrol 類 中 的 一 個 靜 態(tài) 方 法, 不 能 被 重 載(Override)。 它 不 直 接 處 理 消 息, 而 是 交 由wndproc 方 法 處 理, 并 為wndproc 方 法 提 供 一 個 異 常 處 理 模 塊。Mainwndproc 方 法 聲 明 如 下:
procedure MainWndProc(var Message: TMessage);
Wndproc 是 在Tcontrol 類 中 定 義 的 一 個 虛 擬 方 法, 由 它 調(diào) 用dispatch 方 法 來 進 行 消 息 的 分 配, wndproc 方 法 聲 明 如 下:
procedure WndProc(var Message: TMessage); virtual;
dispatch 方 法 是 在Tobject 根 類 中 定 義 的, 其 聲 明 如 下:
procedure Tobject.dispatch(var Message); 傳 遞 給dispatch 的 消 息 參 數(shù) 必 須 是 一 個 記 錄 類 型, 且 這 個 記 錄 中 第 一 個 入 點 必 須 是 一 個cardinal 類 型 的 域(field), 它 包 含 了 要 分 配 的 消 息 的 消 息 號 碼. 例 如:
type
Tmessage=record
Msg:cardinal;
wparam:word;
lparam:longint; .
result:longint;
end;
而Dispatch 方 法 會 根 據(jù) 消 息 號 碼 調(diào) 用 構(gòu) 件 的 最 后 代 類 中 處 理 此 消 息 的 句 柄 方 法. 如 果 此 構(gòu) 件 和 它 的 祖 先 類 中 都 沒 有 對 應(yīng) 此 消 息 的 處 理 句 柄,Dispatch 方 法 便 會 調(diào) 用Defaulthandler 方 法.Defaulthandler 方 法 是 定
義 于Tobject 中 的 虛 擬 方 法, 其 聲 明 如 下:
procedure Defaulthandler(var Message);virtual;
Tobject 類 中 的Defaulthandler 方 法 只 是 實 現(xiàn) 簡 單 的 返 回 而 不 對 消 息 進 行 任 何 的 處 理. 我 們 可 以 通 過 對 此 虛 擬 方 法 的 重 載, 在 子 類 中 實 現(xiàn) 對 消 息 的 缺 省 處 理. 對 于VCL 中 的 構(gòu) 件 而 言, 其Defaulthandler 方 法 會 啟
動 windows API 函 數(shù)Defwindowproc 對 消 息 進 行 處 理.
二.DELPHI 中 的 消 息 處 理 句 柄
在DELPHI 中 用 戶 可 以 自 定 義 消 息 及 消 息 處 理 句 柄. 消 息 處 理 句 柄 的 定 義 有 如 下 幾 個 原 則:
1.消 息 處 理 句 柄 方 法 必 須 是 一 個 過 程, 且 只 能 傳 遞 一 個Tmessage 型 變 量 參 數(shù). 2.方 法 聲 明 后 要 有 一 個message 命 令, 后 接 一 個 在0 到32767 之 間 的 消 息 標 號( 整 型 常 數(shù)). 3.消 息 處 理 句 柄 方 法 不 需 要 用override 命 令 來 顯 式 指 明 重 載 祖 先 的 一 個 消 息 處 理 句 柄, 另 外 它 一 般 聲 明 在 構(gòu) 件 的protected 或private 區(qū). 4.在 消 息 處 理 句 柄 中 一 般 先 是 用 戶 自 己 對 消 息 的 處 理, 最 后 用inherited 命 令 調(diào) 用 祖 先 類 中 對 應(yīng) 此 消 息 的 處 理 句 柄( 有 些 情 況 下 可 能 正 相 反). 由 于 可 能 對 祖 先 類 中 對 此 消 息 的 處 理 句 柄 的 名 字 和 參 數(shù) 類 型 不 清 楚, 而 調(diào) 用 命 令inherited 可 以 避 免 此 麻 煩, 同 樣 如 果 祖 先 類 中 沒 有 對 應(yīng) 此 消 息 的 處 理 句 柄,inherited 就 會 自 動 調(diào) 用Defaulthandler 方 法.( 當 然 如 果 要 屏 蔽 掉 此 消 息, 就 不 用inherited 命 令 了)。
消 息 處 理 句 柄 方 法 聲 明 為:
procedure Mymsgmethod(var message:Tmessage); message Msgtype;
同 樣 用 戶 也 可 以 定 義 自 己 的 消 息, 用 戶 自 定 義 消 息 應(yīng) 從WM_USER 開 始.
自 定 義 消 息 及 消 息 處 理 句 柄 舉 例 如 下:
const my_paint=Wm_user+1;
type
Tmypaint=record
msgid:cardinal;
msize:word;
mcolor:longint;
msgresult:longint;
end;
type
Tmycontrol=class(TCustomControl)
protected
procedure change(var message:Tmypaint); message my_paint;
.....
end;
......
procedure Tmycontrol.change(var message:Tmypaint);
begin
size:=message.msize; { 設(shè) 置Tmybutton 尺 寸 屬 性}
color:=message.mcolor; { 設(shè) 置Tmybutton 顏 色 屬 性}
{do something else}
inherited; { 交 由Tcustomcontrol 處 理}
end;
三. 過 濾 消 息
過 濾 消 息 又 稱 消 息 陷 阱。 在 一 定 情 況 下, 用 戶 可 能 需 要 屏 蔽 某 些 消 息. 或 者 截 獲 某 些 消 息 進 行 處 理。 由 以 上 介 紹 可 以 看 出 過 濾 消 息 一 般 有 三 種 途 徑:(1). 重 載 構(gòu) 件 繼 承 的 虛 擬 方 法wndproc. (2). 針 對 某
消 息 編 寫 消 息 處 理 句 柄. (3). 重 載 構(gòu) 件 繼 承 的 虛 擬 方 法Defhandler, 在 其 中 對 消 息 進 行 處 理。 其 中 常 用 的 方 法 是 方 法(2), 在 上 節(jié) 中 已 介 紹 過 了, 方 法(1) 與 方 法(3) 相 似, 這 里 只 簡 單 介 紹 一 下 方 法(1)。
重 載 虛 擬 方 法wndproc 的 一 般 過 程 如 下:
procedure Tmyobject.wndproc(var message:Tmessage);
begin
{... 判 斷 此 消 息 是 否 該 處 理..}
inherited wndproc(message);
{ 未 處 理 的 消 息 交 由 父 輩wndproc 方 法 處 理}
end;
由 此 可 以 看 出 在wndproc 方 法 中 處 理 消 息 的 優(yōu) 勢 是 可 以 過 濾 整 個 范 圍 內(nèi) 的 消 息, 而 不 必 為 每 個 消 息 指 定 一 個 處 理 句 柄, 事 實 上Tcontrol 構(gòu) 件 中 就 是 利 用 它 來 過 濾 并 處 理 所 有 的 鼠 標 消 息 的(
從WM_mousefirst 到WM_mouselast, 如 下 代 碼 示). 同 樣 利 用 它 也 可 以 阻 止 某 些 消 息 被 發(fā) 送 給 處 理 句 柄。
procedure TControl.WndProc(var Message: TMessage);
begin
if (Message.Msg>=WM_MOUSEFIRST) and
(Message.Msg <= WM_MOUSELAST)
then
if Dragging then { 處 理 拖 曳 事 件}
DragMouseMsg(TWMMouse(Message))
else
... { 處 理 其 他 鼠 標 消 息}
end;
Dispatch(Message);
{ 否 則 正 常 發(fā) 送 消 息}
end;
下 例 為 一 簡 單 的 自 定 義 構(gòu) 件 例 子 :
Tmyedit 類 是 從Tedit 類 派 生 出 的 一 個 新 類, 它 的 特 點 是 在 運 行 中 不 能 獲 得 焦 點, 不 能 由 鍵 盤 輸 入( 有 點 類 似Tlabel 構(gòu) 件). 我 們 可 在 其wndproc 方 法 中 過 濾 出WM_setfocus,WM_mousemove 消 息 并 進 行 處 理 來 達 到 上 述
要 求, 源 程 序 如 下:
unit myedit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics,
Controls, Forms, Dialogs,
StdCtrls;
type
Tmyedit = class(TEdit)
private
{ Private declarations }
protected
{ Protected declarations }
{ other fields and methods}
procedure wndproc(var message:Tmessage);override;
public
{ Public declarations }
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [Tmyedit]);
end;
procedure Tmyedit.wndproc(var message:tmessage);
begin
if message.msg=wm_mousemove then
begin
cursor:=crarrow;
{ 設(shè) 置 光 標 為crarrow, 而 不 是 缺 省 的crBeam 光 標}
exit;
end;
if message.msg=wm_SetFocus then exit;
{屏蔽掉WM_setfocus消息,不讓Tmyedit控件獲得輸入焦點}
inherited wndproc(message);
{其他消息交父輩wndproc處理}
end;
end.
您 可 以 將Tmyedit 加 到Component Palette 中 檢 驗 其 性 能。
由 以 上 介 紹 可 以 看 出, 只 有 清 楚 了Delphi VCL 中 的 消 息 處 理 機 制, 掌 握 好 處 理 各 種 消 息 的 方 法 和 時 機( 必 要 時 要 借 助 各 種 工 具, 如winsight32,spy 等), 并 結(jié) 合OOP 語 言 的 特 點, 我 們 才 可 能 編 出 高 質(zhì) 量 的 構(gòu) 件。 這 當 然 要 靠 讀 者 在 實 踐 中 不 斷 摸 索, 積 累 經(jīng) 驗。
南京理工大學(xué)自控系研96 馬勇