Delphi中对消息的处理

来源:互联网 发布:三国志13优化补丁 编辑:程序博客网 时间:2024/04/28 08:45
Delphi中对消息的处理
 
刘文彦  张  翔
 
摘   要:本文对覆盖消息和自定义消息的处理方法进行讨论,总结出两类消息处理的步骤,
     并通过例程加以实现。
关键词:Delphi; 消息; 通讯
 
1. 引言
    在Windows操作系统中,可以同时运行多个应用程序,并且保持相对的独立性。Windows和应用程序之间是通过发送消息的方法互相联系。Windows为每一个应用程序建立一个消息队列,当应用程序执行某一操作时,将产生相应的消息事件,Windows将事件放入消息队列中等候应用程序取走,应用程序取走消息后,将执行相应程序命令,处理完毕后再取下一条消息。同时,消息也可以在不同的应用程序中进行传递,这就保证了应用程序之间的相互联系和通讯。
2.消息分析
    处理Windows发往各个应用程序的消息是Windows编程的重要内容之一,深刻了解消息的处理方法是编写一个好的应用程序的重要基础。Delphi中提供了对消息的处理方法,并把Windows中的消息转化为自己的组件。消息的处理过程见图1。

               

                             图1
 
    在Delphi中处理Windows预定义的消息通常叫覆盖消息,另一类是自定义消息。Windows在消息处理过程中为每一个消息确定了一个消息索引号,其范围是1~49151。Windows保留了1~1024范围。所以,覆盖消息的索引号在1~1024范围内,而自定义的消息就不要与预定义的消息发生冲突。下面对两类消息的处理方法做一说明。
2.1 覆盖消息
    覆盖消息是将Windows预定义的消息进行覆盖。覆盖消息的原理是通过给新的消息处理方法赋予原消息索引号。这样,当某个事件产生消息的发生事件时,根据其索引号得到新的消息处理方法。覆盖消息的处理步骤:
1)确定所需处理的消息
    确定消息是确定覆盖的系统消息,不同的事件有不同的消息,例如:鼠标单击窗口中的标题栏(窗口中的蓝色彩条)所产生的消息是WM_SYSCOMMAND。
2)在程序中声明所处理的消息(覆盖原消息)
在派生类的protected部分声明消息处理方法,此方法必须是过程:例如:
Procedure mymessage(var msg:Tmessage);
            message WM_messageindex;
    在protected中声明主要是在该类的封装时将其私有化(只允许该类使用),mymessage为此消息的过程名,用关键字message将WM_messageindex的索引号分配给mymessage,即覆盖WM_messageindex消息。WM_messageindex可以是前面提到的WM_SYSCOMMAND消息。
3)编写消息处理过程
    在程序的implementation部分编写消息的实现代码。具体如下:
    Procedure mymessage(var msg:Tmessage);
    Begin
     //所要执行的具体内容。
    End;
2.2 自定义消息
    自定义消息是声明Windows没有预定义的消息,因为不是预定义的消息,所以要编写程序,发送消息。而且用户可以定义一些本消息自带的参数。通过自定义消息,作者可以编写具有特色的应用程序。
    自定义消息的步骤:
1)声明消息的索引号
    前面已经提到了消息索引号的范围以及分配情况。在Delphi中常量WM_USER=1024可以用做自定义消息索引号的起始值,如:
  const
    WM_mymessage=WM_USER+$100;
    但要注意的是一些Windows的标准组件已经占用了1024以外的索引号,为了避免这样的冲突,在Delphi中有另处一个常量WM_APP=32768,建议自定义消息的索引号以WM_APP为起点
,如:
  const
    WM_mymessage=WM_APP+$100
2)定义消息记录类型
    在定义完消息的索引号后,还需要定义消息的记录类型。消息记录类型是传送给消息处理方法的参数结构类型。整个消息记录类型共128bits。定义消息记录类型时记录大小不能超出此范围。下面是一个消息记录类型的例子:
Type
  TWMmymessage=record
  Msg:Cardinal;//该记录对应的消息。
  Name:DWORD;//对应参数wParam
  Time:DWORD;//对应参数1Param;
  Result:Longint;
end;
3)在程序中声明所处理的消息
    声明消息的方法和声明覆盖消息的方法是相同的,使用规则也是一样的。
4)编写消息处理过程
    和前面提到的覆盖消息处理过程方法一样,可以参考前面的例子进行编写。
5)发送自定义消息
    自定义消息不是通过系统发生的某一件事所产生,而是需要我们自己发送到消息队列中。这就涉及到消息的发送问题,在用户发送消息时可以使用下面两个Windows的API函数:
   ① LRESULT SendMessage(
               HWND hWnd,
               UINT Msg,
               WPARAM wParam,
               LPARAM 1Param);
   ② BOOL PostMessage(
               HWND hWnd,
               UINT Msg,
               WPARAM wParam,
               LPARAM 1Param);
3. 应用程序设计
3.1 程序实例
    下面是该程序的部分代码:
unit Unit1;
interface
uses
  Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
  shellapi,StdCtrls;//因为要用到Windows//API函数所以在此声明Shellapi
//定义消息索引号
const
  WM_mymessage=WM_USER+$100;
//定义消息类型
Type
  TWMmymessage=record
    Msg:Cardinal;//该记录对应的消息。
    Name:DWORD;//对应参数wParam
    Time:DWORD;//对应参数1Param;
    Result:Longint;
  end;
type
  TForm1=class(TForm)
    Label1:TLabel;
    label2:TLabel;
    wp:TLabel;
    lp:TLabel;
    Button1:TButton;
    Button2:TButton;
    Edit1:TEdit;
    Edit2:TEdit;
    Procedure            Button1Click(Sender:TObject);
    Procedure            Button2Click(Sender:TObject);
  private
    {Private declarations}
    procedure            mytitlemessage(var msg:TWmsyscommand);message
WM_SYSCOMMAND;
    Procedure            myownermessage(var msg:tWMmymessage);message
WM_mymessage);message
WM_mymessage;
  public
    {Public declarations}
  end;
var
  Form1:TForm1;
implementation
{$R*.DFM}
//覆盖消息的处理过程
procedure          Tform1.mytitlemessage(var msg:TWmsyscommand);
begin
  //得到消息的参数
  case msg.CmdType of
    SC_CLOSE:showmessage (您单击了关闭按扭);//按了关闭按扭
    SC_MAXIMIZE:showmessage (您单击了最大化按扭);//按了最大化按扭
    SC_MINIMIZE:showmessage (您单击了最小化按扭);//按了最小化按扭
  end;
 inherited;
end;
//自定义消息处理
procedure             Tform1.myownermessage(var msg:TWMmymessage);
begin
    //得到消息的参数
    wp.Caption:=inttostr(msg.name);
    lp.caption:=inttostr(msg.time);
end;
//用sendmessage函数发送消息
procedure                  TForm1.Button1Click(Sender:TObject);
var
  hwn:hwnd;
begin
  //得到当前窗口的句柄
  hwn:=findwindow(`tform1',`消息处理');
  //其中edit1.text、edit2.text为所要传递
//消息的参数
Sendmessage(hwn,cardinal(WM_mymessage),
strtoint(edit1.text),strtoint(edit2.text);
end;
//用postmessage函数传递消息
procedure      Tform1.Button2Click(Sender:TObject);
var
  hwn:hwnd;
begin
    //得到当前窗口的句柄
    hwn:=findwindow('tform1','消息处理');
    //其中edit1.text、edit2.text为所要传递//消息的参数
    postmessage(hwn,cardinal(WM_mymessage)),
    strtoint(edit1.text),strtoint(edit2.text);
  end;
end.
3.2 程序说明
    该程序实现对标题栏单击事件所产生的消息覆盖,当用户单击标题栏的三个按扭时,弹出对话框提示用户操作。
    本程序已在Delphi 5.0和Windows 98中调试通过。
4. 结论
    1)应用程序中有许多需要处理的消息,只要知道消息的索引号就可以对发向本应用程序的
消息进行特殊的处理,然后返回其默认的消息参数。比如Windows系统中的关闭操作,向各个应用程序发送的消息是WM-QUERYENDSESSION,这样可以在应用程序中覆盖这个消息来完成关闭程序所需要完成的工作,不影响Windows的正常关闭,而且返回其适当的值可以禁止Windows的关闭。这对制作监控类的应用软件是非常重要的。
    2)通过自定义消息,可以实现不同应用程序之间的通讯。在开发具有多个可执行文件的软
件时,可以通过自定义消息来完成两个程序之间的通讯。
参考文献:
[1]朱宏伟。Delphi5.0编程指南。北京:冶金工业出版社。2000.1
[2]新智工作室。Delphi5.0基础与提高。北京:电子工业出版社。2000.3
[3]吕宗智、汪世攀。Delphi实用技术精粹。北京:人民邮电出版社。2000.3
 
原创粉丝点击