设为首页收藏本站

Delphi乐园 开发者的家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2137|回复: 0

Windows消息机制的应用 [复制链接]

Rank: 4

  • TA的每日心情
    慵懒
    2013-8-10 13:48:45
  • 签到天数: 9 天

    [LV.3]偶尔看看II

    金钱
    60935
    12142
    0
    在线时间
    6 小时
    阅读权限
    10
    精华
    0
    积分
    0
    UID
    10
    发表于 2012-7-6 10:43:01 |显示全部楼层
    分享到:
    一.自定义消息号和消息结构

    const  WM_5001=WM_USER+5001;  WM_5002=WM_USER+5002;  WM_5003=WM_USER+5003;  WM_6001=WM_USER+6001;type  //自定义消息结构  PMsgRec = ^TMsgRec;  TMsgRec = record    msgNo   : Cardinal;    msgText: string;  end;


    二.消息分发
        向特定的对象分发消息:Dispatch函数
        原理:

      在TObject类中,有一个Dispatch()方法和一个DefaultHandler()方法,它们都是与消息
        分发机制相关的。
        Dispatch()负责将特定的消息分发给合适的消息处理函数。首先它会在对象本身类型
        的类中寻找该消息的处理函数,如果找到,则调用它;如果没有找到而该类覆盖了TObject
        的DefaultHandler(),则调用该类的DefaultHandler();如果两者都不存在,则继续在其基
        类中寻找,直至寻找到TObject这一层,而TObject已经提供了默认的DefaultHandler()
        方法。

        消息接收类:TMsgAccepter

    //自定义消息接收类  TMsgAccepter=class  private    procedure Msg5001Accepter(var msg:TMsgRec); message WM_5001;  public    procedure defaultHandler(var message); override;  end;implementationuses  Main;{ TMsgAccepter }procedure TMsgAccepter.Msg5001Accepter(var msg: TMsgRec);begin    FrmMain.Memo1.Lines.Add('接收类已收到5001消息,并对其进行了处理!')end;procedure TMsgAccepter.defaultHandler(var message);var  theMsg:TMsgRec;begin  theMsg:=TMsgRec(message);  FrmMain.Memo1.Lines.Add('接收类收到消息请求,但该消息号无指定处理函数!消息号为:'+IntToStr(theMsg.msgNo));end;

        a)向对象theMsgAccepter分发消息WM_5001(有对应处理函数

    var  theMsg:TMsgRec;begin  theMsg.msgNo:=WM_5001;  theMsg.msgText:='';  theMsgAccepter.Dispatch(theMsg);end;

          运行结果:
          
        b)向对象theMsgAccepter分发消息WM_6001(无对应处理函数

    var  theMsg:TMsgRec;begin  theMsg.msgNo:=WM_6001;  theMsg.msgText:='';  theMsgAccepter.Dispatch(theMsg);end;

          运行结果:
          

    三.消息投递:向特定窗口投递消息
         消息响应窗口:TFrmMsgProcess


      TFrmMsgProcess = class(TForm)    Memo1: TMemo;    procedure FormCreate(Sender: TObject);  private    { Private declarations }    procedure Msg5002Accepter(var msg:TMessage); message WM_5002;    procedure Msg5003Accepter(var msg:TMessage); message WM_5003;  public    { Public declarations }  end;var  FrmMsgProcess: TFrmMsgProcess;implementationuses  Main;{$R *.dfm}{ TFrmMsgProcess }procedure TFrmMsgProcess.Msg5002Accepter(var msg:TMessage);var  pTheMsgMsgRec;begin   Self.Memo1.Lines.Add('窗口已收到5002号消息,并开始进行处理。。。');   Self.Memo1.Lines.Add('窗口收到的字符串参数信息为:'+String(msg.WParam));   pTheMsg:=PMsgRec(msg.LParam);   Self.Memo1.Lines.Add('窗口收到的结构体参数信息为:'+pTheMsg.msgText);      Self.Memo1.Lines.Add('窗口对5002号消息的处理已完成!');end;procedure TFrmMsgProcess.FormCreate(Sender: TObject);begin   self.Memo1.Color:=clblack;   self.Memo1.Font.Color:=clgreen;end;procedure TFrmMsgProcess.Msg5003Accepter(var msg: TMessage);begin   FrmMain.Memo1.Lines.Add('窗口已收到5003号消息,并开始进行处理。。。');   Sleep(1000);   FrmMain.Memo1.Lines.Add('窗口对5003号消息的处理已完成!');end;

          a)异步方式:Postmessage,发出后不等待,直接返回

    begin  Self.Memo1.Lines.Add('主线程向子窗口发送5003号消息。。。');  PostMessage(FrmMsgProcess.Handle,WM_5003,0,0);  Self.Memo1.Lines.Add('主线程消息发送函数已结束!');end;

            运行结果:
          

         b)同步方式:SendMessage,等窗口响应后,再返回

    begin  Self.Memo1.Lines.Add('主线程向子窗口发送5003号消息。。。');  SendMessage(FrmMsgProcess.Handle,WM_5003,0,0);  Self.Memo1.Lines.Add('主线程消息发送函数已结束!');end;

           运行结果:
          
         c)带参数信息的消息投递

                 发送“字符串或结构体”时,尽可能用sendMessage,否则,可能内存中的内容
            已被更改,而窗口消息响应函数还未处理。


    var  msgStr:string;  theMsg:TMsgRec;begin  msgStr:='WM_5002消息的字符串说明';  theMsg.msgNo:=WM_5002;  theMsg.msgText:='WM_5002消息的结构体说明';  SendMessage(FrmMsgProcess.Handle,WM_5002,WParam(PChar(msgStr)),LParam(@theMsg));end;

             运行结果:
             
    四.其他
          a)wparam与lparam

             wParam: 原win16系统中,word类型的整数,16位;现在的win32系统中,扩展为32位整型。
             lParam:   原win16系统中,long类型的整数,32位;现在的win32系统中,32位整型。

             注:WPARAM常常代表一些控件的ID或者高位底位组合起来分别表示鼠标的位置,如果
               消息的发送者需要将某种结构的指针或者是某种类型的句柄时,习惯上用LPARAM来传递。

          b)常用消息处理函数

        Peekmessage()   从消息队列中读消息
            Getmessage()   可以有选择的从消息列表中得到消息,一般用在window的窗口过程函数里面
            DispatchMessage()   用来派送消息到窗口过程
            TranslateMessage()   用于将Virtul-Key消息翻译为字符消息
            Postthreadmessage()   用于向线程发送消息
            Postmessage()   用于将消息传送到窗口的消息队列
            SendMessage()不经过消息队列而直接发送给窗口的

          c)窗口过程函数

                从消息队列中取消息
                重写窗口默认“窗口过程函数
    您需要登录后才可以回帖 登录 | 立即注册

    空间、域名、优惠稳定。香港空间1元,美国2元。

    手机版|Delphi乐园 ( 冀ICP备11023363号-7 )    

    GMT+8, 2016-10-23 02:13

    Powered by Discuz! X2

    © 2001-2011 Comsenz Inc.

    公网安备 14090202000504号

    回顶部