AD商业广告自由选择
AD商业广告自由选择

DELPHI中的消息处理机制

正文概述 开源人   2024-10-29 18:58:44  
Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具.由于它采用了具有弹性的和可重用的面向对象Pascal(object-oriented pascal)语言,并有强大的数据库引擎(BDE),快速的代码编译器,同时又提供了众多出色的构件.受到广大编程人员的青睐.在众多的编程语言(如VB,PowerBuilder,Powerpoint等)中脱颖而出.xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
其中一个DELPHI强于其他编程语言(如VB4.0)的地方就是在DELPHI中可自定义消息,并可直接处理消息.这对于那些希望编写自己的构件(Component),或者希望截获.过滤消息的用户来说是必不可少的.因为编写构件一般要对相应的消息进行处理.下面就对Delphi中消息处理机制进行一下介绍。xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
一.DELPHIVCL中消息的传递xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Delphi中每一个VCL(Visual Component Library)构件(如Tbutton,Tedit等)都有一内在的消息处理机制,其基本点就是构件类接收到某些消息并把它们发送给适当的处理方法,如果没有特定的处理方法,则调用缺省的消息处理句柄。xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
其中mainwndproc是定义在Twincontrol类中的一个静态方法,不能被重载(Override)。它不直接处理消息,而是交由wndproc方法处理,并为wndproc方法提供一个异常处理模块。Mainwndproc方法声明如下:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure MainWndProc(var Message: TMessage);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Wndproc是在Tcontrol类中定义的一个虚拟方法,由它调用dispatch方法来进行消息的分配,wndproc方法声明如下:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure WndProc(var Message: TMessage); virtual;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
dispatch方法是在Tobject根类中定义的,其声明如下:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure Tobject.dispatch(var Message);传递给dispatch的消息参数必须是一个记录类型,且这个记录中第一个入点必须是一个cardinal类型的域(field),它包含了要分配的消息的消息号码.例如:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
typexAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Tmessage=recordxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Msg:cardinal;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
wparam:word;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
lparam:longint; .xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
result:longint;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
而Dispatch方法会根据消息号码调用构件的最后代类中处理此消息的句柄方法.如果此构件和它的祖先类中都没有对应此消息的处理句柄,Dispatch方法便会调用Defaulthandler方法.Defaulthandler方法是定义于Tobject中的虚拟方法,其声明如下:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure Defaulthandler(var Message);virtual;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Tobject类中的Defaulthandler方法只是实现简单的返回而不对消息进行任何的处理.我们可以通过对此虚拟方法的重载,在子类中实现对消息的缺省处理.对于VCL中的构件而言,其Defaulthandler方法会启动windowsAPI函数Defwindowproc对消息进行处理.xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
二.DELPHI中的消息处理句柄xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
在DELPHI中用户可以自定义消息及消息处理句柄.消息处理句柄的定义有如下几个原则:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
消息处理句柄方法必须是一个过程,且只能传递一个Tmessage型变量参数.xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
方法声明后要有一个message命令,后接一个在0到32767之间的消息标号(整型常数).xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
消息处理句柄方法不需要用override命令来显式指明重载祖先的一个消息处理句柄,另外它一般声明在构件的protected或private区.xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
在消息处理句柄中一般先是用户自己对消息的处理,最后用inherited命令调用祖先类中对应此消息的处理句柄(有些情况下可能正相反).由于可能对祖先类中对此消息的处理句柄的名字和参数类型不清楚,而调用命令inherited可以避免此麻烦,同样如果祖先类中没有对应此消息的处理句柄,inherited就会自动调用Defaulthandler方法.(当然如果要屏蔽掉此消息,就不用inherited命令了)。xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
消息处理句柄方法声明为:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure Mymsgmethod(var message:Tmessage); message Msgtype;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
同样用户也可以定义自己的消息,用户自定义消息应从WM_USER开始.xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
自定义消息及消息处理句柄举例如下:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
const my_paint=Wm_user+1;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
typexAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Tmypaint=recordxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
msgid:cardinal;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
msize:word;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
mcolor:longint;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
msgresult:longint;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
typexAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Tmycontrol=class(TCustomControl)xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
protectedxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure change(var message:Tmypaint); message my_paint;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
.....xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
......xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure Tmycontrol.change(var message:Tmypaint);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
beginxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
size:=message.msize;{设置Tmybutton尺寸属性}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
color:=message.mcolor;{设置Tmybutton颜色属性}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{do something else}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
inherited; { 交 由Tcustomcontrol 处 理}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
 xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
三.过滤消息xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
过滤消息又称消息陷阱。在一定情况下,用户可能需要屏蔽某些消息.或者截获某些消息进行处理。由以上介绍可以看出过滤消息一般有三种途径:(1).重载构件继承的虚拟方法wndproc.(2).针对某xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
消息编写消息处理句柄.(3).重载构件继承的虚拟方法Defhandler,在其中对消息进行处理。其中常用的方法是方法(2),在上节中已介绍过了,方法(1)与方法(3)相似,这里只简单介绍一下方法(1)。xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
重 载 虚 拟 方 法wndproc 的 一 般 过 程 如 下:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure Tmyobject.wndproc(var message:Tmessage);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
beginxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{...判断此消息是否该处理..}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
inheritedwndproc(message);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{未处理的消息交由父辈wndproc方法处理}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
由此可以看出在wndproc方法中处理消息的优势是可以过滤整个范围内的消息,而不必为每个消息指定一个处理句柄,事实上Tcontrol构件中就是利用它来过滤并处理所有的鼠标消息的(从WM_mousefirst到WM_mouselast,如下代码示).同样利用它也可以阻止某些消息被发送给处理句柄。xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure TControl.WndProc(var Message: TMessage);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
beginxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
if (Message.Msg>=WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) thenxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
if Dragging then{处理拖曳事件}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
DragMouseMsg(TWMMouse(Message))xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
elsexAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
...{处理其他鼠标消息}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Dispatch(Message);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{否则正常发送消息}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
下例为一简单的自定义构件例子:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Tmyedit类是从Tedit类派生出的一个新类,它的特点是在运行中不能获得焦点,不能由键盘输入(有点类似Tlabel构件).我们可在其wndproc方法中过滤出WM_setfocus,WM_mousemove消息并进行处理来达到上述xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
要求,源程序如下:xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
unit myedit;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
interfacexAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
usesxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Windows, Messages, SysUtils, Classes, Graphics,Controls, Forms, Dialogs,xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
StdCtrls;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
typexAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
Tmyedit = class(TEdit)xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
privatexAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{ Private declarations }xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
protectedxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{ Protected declarations }xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{ other fields and methods}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure wndproc(var message:Tmessage);override;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
publicxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{ Public declarations }xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
publishedxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{ Published declarations }xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure Register;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
implementationxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure Register;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
beginxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
RegisterComponents('Samples', [Tmyedit]);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
procedure Tmyedit.wndproc(var message:tmessage);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
beginxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
if message.msg=wm_mousemove thenxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
beginxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
cursor:=crarrow;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{设置光标为crarrow,而不是缺省的crBeam光标}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
exit;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
if message.msg=wm_SetFocus thenxAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
exit;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{屏蔽掉WM_setfocus消息,不让Tmyedit控件获得输入焦点}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
inherited wndproc(message);xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
{其他消息交父辈wndproc处理}xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end;xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
end.xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
您可以将Tmyedit加到Component Palette中检验其性能。xAZ1234FCOM专注游戏工具及源码例子分享
xAZ1234FCOM专注游戏工具及源码例子分享
由以上介绍可以看出,只有清楚了Delphi VCL中的消息处理机制,掌握好处理各种消息的方法和时机(必要时要借助各种工具,如winsight32,spy等),并结合OOP语言的特点,我们才可能编出高质量的构件。这当然要靠读者在实践中不断摸索,积累经验。


声明:本文系互联网搜索而收集整理,不以盈利性为目的,文字、图文资料源于互联网且共享于互联网。
如有侵权,请联系 yao4fvip#qq.com (#改@) 删除。