如何知道组件的某一事件用什么消息触发的?(100分)

  • 主题发起人 主题发起人 asaili
  • 开始时间 开始时间
A

asaili

Unregistered / Unconfirmed
GUEST, unregistred user!
比如:
TTREEVIEW的onchange 事件是用什么消息触发的,这样我可以在别的地方想该TREEVIEW
发一个这样的消息就可以触发onchange时间了。
怎么才能知道是什么消息了?看VCL代码吗?请教高手们怎么做?
 
由键盘和鼠标click出发,你发消息你想怎么确定自己要选中那个TreeNode?

-----
http://www.8421.org
 
我想要的结果是这样的。
TREEVIEW 当前选中的TREENODE并没有改变,这样不会触发数据刷新。数据刷新是写在
TREEVIEW的ONCHANGE事件中的。因此我想给这个TREEVIEW发一个CHANGE的事件,欺骗TREEVIEW
进行数据刷新。

请大侠帮忙
 
想欺骗,那就自己在其他事件或是过程发送消息(可以是封装的消息,也可以是自定义消息)
,封装消息由delphi组件自己处理,自定义消息的话要你自己写处理过程(dispatch……message)
,都可以达到欺骗的效果!
 
自己定义一个消息,看看下面的例子
 

Delphi 中 每 一 个VCL(Visual Component Library) 构 件( 如Tbutton,Tedit 等) 都 有 一 内 在 的 消 息 处理 机 制, 其 基 本 点 就 是 构 件 类 接 收 到 某 些 消 息 并 把 它 们发 送 给 适 当 的 处 理 方 法, 如 果 没 有 特 定 的 处 理 方 法,
则 调用 缺 省 的 消 息 处 理 句 柄。
其 中mainwndproc 是 定义 在Twincontrol 类 中 的 一 个 静 态 方 法, 不 能 被 重 载(Override)。它 不 直 接 处 理 消 息, 而 是 交 由wndproc 方 法 处 理, 并 为wndproc 方 法 提 供 一 个 异 常 处 理 模 块。Mainwndproc 方 法 声 明 如 下:

procedure MainWndProc(var Message: TMessage);

Wndproc 是 在Tcontrol 类 中 定 义 的 一 个 虚 拟 方 法, 由 它 调 用dispatch 方 法 来 进 行 消息 的 分 配, wndproc 方 法 声 明 如 下:

procedure WndProc(var Message: TMessage); virtual;

dispatch 方 法 是 在Tobject 根 类 中 定 义 的, 其 声 明 如 下:

procedure Tobject.dispatch(var Message); 传 递 给dispatch 的 消 息 参 数 必 须 是 一 个 记 录 类 型, 且这 个 记 录 中 第 一 个 入 点 必 须 是 一 个cardinal 类 型 的 域(field), 它 包 含 了 要 分 配 的 消 息 的 消 息 号 码. 例 如:

type

Tmessage=record

Msg:cardinal;

wparam:word;

lparam:longint; .

result:longint;

end;
而Dispatch 方 法 会 根据 消 息 号 码 调 用 构 件 的 最 后 代 类 中 处 理 此 消 息 的 句 柄 方法. 如 果 此 构 件 和 它 的 祖 先 类 中 都 没 有 对 应 此 消 息 的 处 理句 柄,Dispatch 方 法 便 会 调 用Defaulthandler 方 法.Defaulthandler 方法 是 定 义 于Tobject 中 的 虚 拟 方 法, 其 声 明 如 下:

procedure Defaulthandler(var Message);virtual;

Tobject 类 中 的Defaulthandler 方 法 只 是 实 现 简 单 的 返 回 而 不 对 消 息 进 行 任 何 的 处 理. 我们 可 以 通 过 对 此 虚 拟 方 法 的 重 载,
在 子 类 中 实 现 对 消 息 的缺 省 处 理. 对 于VCL 中 的 构 件 而 言, 其Defaulthandler 方 法 会 启 动 windows API 函 数Defwindowproc 对 消 息 进 行 处 理.

二.DELPHI 中 的 消 息 处 理 句 柄
在DELPHI 中 用 户 可 以自 定 义 消 息 及 消 息 处 理 句 柄. 消 息 处 理 句 柄 的 定 义 有 如 下几 个 原 则:

消 息 处 理 句 柄 方 法 必 须 是 一 个 过 程, 且 只 能 传 递 一 个Tmessage 型 变 量 参 数.
方 法 声 明 后 要 有 一 个message 命 令, 后 接 一 个 在0 到32767 之 间的 消 息 标 号( 整 型 常 数).
消 息 处 理 句 柄 方 法 不 需 要 用override 命 令 来 显 式 指 明 重 载祖 先 的 一 个 消 息 处 理 句 柄, 另 外 它 一 般 声 明 在 构 件 的protected 或private 区.
在 消 息 处 理 句 柄 中 一 般 先 是 用 户 自 己 对 消 息 的 处 理, 最 后用inherited 命 令 调 用 祖 先 类 中 对 应 此 消 息 的 处 理 句 柄( 有些 情 况 下 可 能 正 相 反).
由 于 可 能 对 祖 先 类 中 对 此 消 息 的处 理 句 柄 的 名 字 和 参 数 类 型 不 清 楚, 而 调 用 命 令inherited 可以 避 免 此 麻 烦,
同 样 如 果 祖 先 类 中 没 有 对 应 此 消 息 的 处 理句 柄,
inherited 就 会 自 动 调 用Defaulthandler 方 法.( 当 然 如 果 要屏 蔽 掉 此 消 息, 就 不 用inherited 命 令 了)。
消 息 处 理 句 柄 方 法 声 明 为:
procedure Mymsgmethod(var message:Tmessage); message Msgtype;

同 样 用 户 也 可 以定 义 自 己 的 消 息, 用 户 自 定 义 消 息 应 从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; { 设 置Tmybutton 尺 寸 属 性}

color:=message.mcolor; { 设 置Tmybutton 颜 色 属 性}

{do something else}

inherited; { 交 由Tcustomcontrol 处 理}

end;
三. 过 滤 消 息
过 滤 消 息 又 称 消 息陷 阱。 在 一 定 情 况 下, 用 户 可 能 需 要 屏 蔽 某 些 消 息.
或 者截 获 某 些 消 息 进 行 处 理。 由 以 上 介 绍 可 以 看 出 过 滤 消 息一 般 有 三 种 途 径:(1). 重 载 构 件 继 承 的 虚 拟 方 法wndproc. (2). 针 对 某 消 息 编 写 消 息 处 理 句 柄. (3)
. 重 载 构 件 继 承 的 虚 拟方 法Defhandler, 在 其 中 对 消 息 进 行 处 理。 其 中 常 用 的 方 法是 方 法(2), 在 上 节 中 已 介 绍 过 了, 方 法(1) 与 方 法(3) 相 似,这 里 只 简 单 介 绍 一 下 方 法(1)。

重 载 虚 拟 方 法wndproc 的 一 般 过 程 如 下:

procedure Tmyobject.wndproc(var message:Tmessage);

begin

{... 判 断 此 消 息 是 否 该 处 理..}

inherited wndproc(message);

{ 未 处 理 的 消 息 交 由 父 辈wndproc 方 法 处 理}

end;
由 此 可 以 看 出 在wndproc 方 法 中 处 理 消 息 的 优 势 是 可 以 过 滤 整 个 范 围 内 的 消 息,而 不 必 为 每 个 消 息 指 定 一 个 处 理 句 柄,
事 实 上Tcontrol 构 件中 就 是 利 用 它 来 过 滤 并 处 理 所 有 的 鼠 标 消 息 的( 从WM_mousefirst 到WM_mouselast, 如 下 代 码 示). 同 样 利 用 它 也 可 以 阻 止 某 些 消息 被 发 送 给 处 理 句 柄。

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);

{ 否 则 正 常 发 送 消 息}

end;
下 例 为 一 简 单 的 自定 义 构 件 例 子 :

Tmyedit 类 是 从Tedit 类 派 生 出 的 一 个 新 类, 它 的 特 点 是 在 运 行 中 不 能 获 得 焦点, 不 能 由 键 盘 输 入( 有 点 类 似Tlabel 构 件). 我 们 可 在 其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;

{ 设 置 光 标 为crarrow, 而 不 是 缺 省 的crBeam 光 标}

exit;

end;

if message.msg=wm_SetFocus then exit;

{屏蔽掉WM_setfocus消息,不让Tmyedit控件获得输入焦点}

inherited wndproc(message);

{其他消息交父辈wndproc处理}

end;

end.
您 可 以 将Tmyedit 加到Component Palette 中 检 验 其 性 能。

 
多人接受答案了。
 
后退
顶部