分享

Delphi的消息处理

 独孤求财 2012-03-20

Delphi的消息处理

时间:2011-5-26来源:yang 作者: peng点击: 14次

Delphi的消息处理
Delphi是Borland公司的一种面向对象的可视化软件开发工具。

  Delphi集中了Visual C + +和Visual Basic两者的优点:容易上手、功能强大,特别是在界面设计、数据库编程、网络编程方面更有其独特的优势。
Delphi中的消息

  消息是Windows发出的一个通知,它告诉应用程序某个事件发生了。在Delphi中,大多数情况下Windows的消息被封装在VCL的事件中,我们只需处理相应的VCL事件就可以了,但如果我们需要编写自己的控件、截获或过滤消息就必须深入研究Win32的消息处理机制。

  在Delphi中消息以TMessage记录的方式定义。打开Message.pas文件,我们可以看到Tmessage是这样定义的:

  type

   TMessage = packed record

   Msg: Cardinal;

   case Integer of
  
       0: (WParam: Longint;
  
          LParam: Longint;

          Result: Longint);

       1: (WParamLo: Word;

          WParamHi: Word;

          LParamLo: Word;

          LParamHi: Word;

          ResultLo: Word;

          ResultHi: Word);

  end;

  其中,Msg是区别于其他消息的常量值,这些常量值可以是Windows单元中预定义的常量,也可以是用户自己定义的常量。Wparam通常是一个与消息有关的常量值,也可以是窗口或控件的句柄。LParam通常是一个指向内存中数据的指针。

  Result是消息处理的返回值。Wparam、Lparam和Result都是32位的,如果想访问其中的低16位或高16位可以分别使用WparamLo、WparamHi、 LParamLo、LparamHi、ResultLo和ResultHi。

  在Delphi中除了通用的Tmessage外,还为每个Windows定义了一个特殊的消息记录。我们可以浏览Message.pas文件,下面是键盘的消息记录:

TWMKey = packed record

    Msg: Cardinal;

    CharCode: Word;

    Unused: Word;

    KeyData: Longint;

    Result: Longint;

    与键盘相关的消息如:WM_KEYDOWN、 WM_KEYUP、 WM_CHAR、 WM_SYSKEYDOWN WM_SYSKEYUP、 WM_SYSCHAR的记录也被定义为TWMkey。在Message.pas文件中有以下声明:

    TWMChar = TWMkey; TWMKeyDown =

    TWMkey;TWMKeyUp = TWMkey; TWMSys

    - KeyDown = TWMkey; TWMSysKeyUp =

    TWMkey;TWMSysChar = TWMkey;

    消息的发送

    消息处理就是定义应用程序如何响应Windows的消息。在Delphi中每一个消息都有自己的处理过程,它必须是一个对象中的方法,且只能传递一个Tmessage或其他特殊的消息记录,方法声明后要有一个message命令,后接一个在0到32767之间的常量。

    前面我们提到的消息都是标准的Windows消息(WM_X), 除此之外还有VCL内部消息、通知消息和用户自定义消息。

    VCL内部消息通常以“CM_”开头,用于管理VCL内部的事物。如果改变了某个属性值或组件的其他一些特性后,需要通过内部消息将该变化通知其他组件。例如,激活输入焦点消息是向被激活的或被停用的组件发送的,用于接受或放弃输入焦点。

    另外还有通知消息,一个窗口内的子控件发生了一些事情,需要通知父窗口,这是通过通知消息实现的。它只适用于标准的窗口控件,如按钮、列表框、编辑框等等。打开Message.pas文件,在标准的Windows后就是通知消息的声明:

  const

  {$EXTERNALSYM BN_CLICKED}

     BN_CLICKED = 0;

  {$EXTERNALSYM BN_PAINT}

     BN_PAINT = 1;

  {$EXTERNALSYM BN_HILITE}

   BN_HILITE = 2;

    以上是按钮的通知消息,分别表示用户单击了按钮、按钮应当重画、用户加亮了按钮。

    用户也可以自己定义消息、给自己发送消息和编写消息处理过程。消息的常量值为WM_USER + 100 到$7FFF, 这个范围是Windows为用户自定义消息保留的。

    Delphi消息的发送有三种方法:

    1 .Tcontrol类的Perform对象方法。可以向任何一个窗体或控件发送消息,只需要知道窗体或控件的实例。其声明如下:

function Tcontrol.Perform(Msg: Cardinal; Wparam, Lparam: Longint): Longint

  2 .Windows的API函数SendMessage()和Postmessage()。其声明如下:

  function SendMessage(hWnd: HWND; Msg: UINT;wParam:WPARAM; lParam: LPARAM):LRESULT;stdcall;

  function SendMessage(hWnd: HWND; Msg: UINT;wParam: WPARAM; lParam:LPARAM):LRESULT;stdcall

  PostMessage函数将消息添加到应用程序的消息队列中去。应用程序的消息循环会从消息队列中提取登记的该消息,再发送到相应的窗口中。

  SendMessage函数可以越过消息队列直接向窗口过程发送。所以当Windows需要立刻返回值时使用SendMessage,当需要不同的应用程序依次处理消息时使用PostMessage。而Perform从本质上和SendMessage相似,它们直接向窗口过程发送。SendMessage、Postmessage函数只需要知道窗口的句柄就可以发送消息,所以它们可以向非Delphi窗体发送一条消息,但而Perform必须知道窗体或控件的实例。

  VCL消息处理机制

  在Delphi应用程序的源代码中有语句Application.Run,它的作用是启动消息循环,然后调用Application.ProcessMessage,该函数会在应用程序的消息队列中查找一条消息。当在消息队列中检索到一条消息后,触发Application.OnMessage事件。这样在Windows本身对消息处理之前,就会响应OnMessage事件的处理过程,它优于任何消息处理,而且只接收登记的消息,即前面所述的由PostMessage发送的消息。响应Application.OnMessage事件的处理过程必须是TmessageEvent类型, 其声明如下:

    type TMessageEvent = procedure(var Msg: TMsg; var Handled: Boolean) of object;

  其中TMsg是Windows中定义的消息记录,我们可以这样声明:

  procedure OnMyMessage(var Msg: TMsg; var Handled: Boolean);

  然后把此方法赋给Application.OnMessage事件:

  Application.OnMessage := OnMyMessage;

  OnMessage事件将捕获发送给应用程序的所有消息,这是一个非常繁忙的事件,因此在处理OnMessage事件的处理过程中设置断点进行消息处理是不明智的。

  VCL对象用于接收消息的方法叫MainWndProc。它是定义在Twincontrol类中的静态方法,不能被重载。它不直接处理消息,当消息离开MainWndProc后,消息被传递给对象的WndProc方法,WndProc方法是在Tcontrol类中定义的一个虚拟方法,由它调用Dispatch方法。Dispatch根据传入的Message来寻找相应的处理方法,如果最后找不到,就继续向上到父类中寻找消息处理方法,一直到找到为止,如果找不到则调用Defaulthandler。Defaulthandler方法对消息进行最后的处理,然后把消息传递给Windows的DefWindowProc函数或其他默认的窗口过程。
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多