每一个VCL都有一内在的消息处理机制,其基本点就是构件类接收到某些消息并把它们发送给适当的处理方法,如果没有特定的处理方法,则调用缺省的消息处理句柄。
其中mainwndproc是定义在Twincontrol类中的一个静态方法,不能被重载(Override)。它不直接处理消息,而是交由wndproc方法处理,并为wndproc方法提供一个异常处理模块。
Wndproc是在Tcontrol类中定义的一个虚拟方法,由它调用dispatch方法来进行消息的分配。
dispatch方法是在Tobject根类中定义的,而Dispatch方法会根据消息号码调用构件的最后代类中处理此消息的句柄方法.如果此构件和它的祖先类中都没有对应此消息的处理句柄,Dispatch方法便会调用Defaulthandler方法。
Defaulthandler方法是定义于Tobject中的虚拟方法,只是实现简单的返回而不对消息进行任何的处理.我们可以通过对此虚拟方法的重载,在子类中实现对消息的缺省处理.对于VCL中的构件而言,其Defaulthandler方法会启动windowsAPI函数Defwindowproc对消息进行处理.
过滤消息一般有三种途径:(1)针对某消息编写消息处理句柄.(2)重载构件继承的虚拟方法wndproc.(3)重载构件继承的虚拟方法Defhandler,在其中对消息进行处理。
(1)针对某消息编写消息处理句柄:用户可以自定义消息及消息处理句柄.消息处理句柄的定义有如下几个原则:
消息处理句柄方法必须是一个过程,且只能传递一个Tmessage型变量参数.
不需要用override命令来显式指明重载祖先的一个消息处理句柄,另外它一般声明在构件的protected或private区.
在消息处理句柄中一般先是用户自己对消息的处理,最后用inherited命令调用祖先类中对应此消息的处理句柄.
同样如果祖先类中没有对应此消息的处理句柄,inherited就会自动调用Defaulthandler方法.
(2)重载构件继承的虚拟方法wndproc:在wndproc方法中处理消息的优势是可以过滤整个范围内的消息,而不必为每个消息指定一个处理句柄,事实上Tcontrol构件中就是利用它来过滤并处理所有的鼠标消息的(从WM_mousefirst到WM_mouselast,如下代码示).同样利用它也可以阻止某些消息被发送给处理句柄。
procedure TControl.WndProc(var Message: TMessage);
begin
if (Message.Msg>=WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) then
begin
if Dragging then { 处 理 拖 曳 事 件}
DragMouseMsg(TWMMouse(Message))
else
... { 处 理 其 他 鼠 标 消 息}
end
else
Dispatch(Message); { 否 则 正 常 发 送 消 息}
end;
procedure Tmyedit.wndproc(var message:tmessage);
begin
if message.msg=wm_SetFocus then
exit; {屏蔽掉WM_setfocus消息,不让Tmyedit控件获得输入焦点}
inherited wndproc(message);{其他消息交父辈wndproc处理}
end;