消息的发送
消息处理就是定义应用程序如何响应Windows的消息在Delphi中每一个消息都有自己的处理过程它必须是一个对象中的方法且只能传递一个Tmessage或其他特殊的消息记录方法声明后要有一个message命令后接一个在到之间的常量
前面我们提到的消息都是标准的Windows消息(WM_X) 除此之外还有VCL内部消息通知消息和用户自定义消息
VCL内部消息通常以CM_开头用于管理VCL内部的事物如果改变了某个属性值或组件的其他一些特性后需要通过内部消息将该变化通知其他组件例如激活输入焦点消息是向被激活的或被停用的组件发送的用于接受或放弃输入焦点
另外还有通知消息一个窗口内的子控件发生了一些事情需要通知父窗口这是通过通知消息实现的它只适用于标准的窗口控件如按钮列表框编辑框等等打开Messagepas文件在标准的Windows后就是通知消息的声明:
const
{$EXTERNALSYM BN_CLICKED}
BN_CLICKED = ;
{$EXTERNALSYM BN_PAINT}
BN_PAINT = ;
{$EXTERNALSYM BN_HILITE}
BN_HILITE = ;
以上是按钮的通知消息分别表示用户单击了按钮按钮应当重画用户加亮了按钮
用户也可以自己定义消息给自己发送消息和编写消息处理过程消息的常量值为WM_USER + 到$FFF 这个范围是Windows为用户自定义消息保留的
Delphi消息的发送有三种方法
.Tcontrol类的Perform对象方法可以向任何一个窗体或控件发送消息只需要知道窗体或控件的实例其声明如下
function TcontrolPerform(Msg: Cardinal; Wparam Lparam: Longint): Longint
.Windows的API函数SendMessage()和Postmessage()其声明如下
function SendMessage(hWnd: HWND; Msg: UINTwParamWPARAM; lParam: LPARAM)LRESULTstdcall
function SendMessage(hWnd: HWND; Msg: UINTwParam: WPARAM; lParamLPARAM)LRESULTstdcall
PostMessage函数将消息添加到应用程序的消息队列中去应用程序的消息循环会从消息队列中提取登记的该消息再发送到相应的窗口中
SendMessage函数可以越过消息队列直接向窗口过程发送所以当Windows需要立刻返回值时使用SendMessage当需要不同的应用程序依次处理消息时使用PostMessage而Perform从本质上和SendMessage相似它们直接向窗口过程发送SendMessagePostmessage函数只需要知道窗口的句柄就可以发送消息所以它们可以向非Delphi窗体发送一条消息但而Perform必须知道窗体或控件的实例
VCL消息处理机制
在Delphi应用程序的源代码中有语句ApplicationRun它的作用是启动消息循环然后调用ApplicationProcessMessage该函数会在应用程序的消息队列中查找一条消息当在消息队列中检索到一条消息后触发ApplicationOnMessage事件这样在Windows本身对消息处理之前就会响应OnMessage事件的处理过程它优于任何消息处理而且只接收登记的消息即前面所述的由PostMessage发送的消息响应ApplicationOnMessage事件的处理过程必须是TmessageEvent类型 其声明如下
type TMessageEvent = procedure(var Msg: TMsg; var Handled: Boolean) of object;
其中TMsg是Windows中定义的消息记录我们可以这样声明
procedure OnMyMessage(var Msg: TMsg; var Handled: Boolean);
然后把此方法赋给ApplicationOnMessage事件:
ApplicationOnMessage := OnMyMessage;
OnMessage事件将捕获发送给应用程序的所有消息这是一个非常繁忙的事件因此在处理OnMessage事件的处理过程中设置断点进行消息处理是不明智的
VCL对象用于接收消息的方法叫MainWndProc它是定义在Twincontrol类中的静态方法不能被重载它不直接处理消息当消息离开MainWndProc后消息被传递给对象的WndProc方法WndProc方法是在Tcontrol类中定义的一个虚拟方法由它调用Dispatch方法Dispatch根据传入的Message来寻找相应的处理方法如果最后找不到就继续向上到父类中寻找消息处理方法一直到找到为止如果找不到则调用DefaulthandlerDefaulthandler方法对消息进行最后的处理然后把消息传递给Windows的DefWindowProc函数或其他默认的窗口过程
[] []