C++ builder消息的运用

来源:网络时间:2011-06-27 18:06:11

  一、TApplication的OnMessage事件

  OnMessage事件只处理消息队列中的消息,SendMessage()发送的消息不会被截获。

  任何窗体接收到一个windows消息,都会触发一次此事件

  函数原型:

  typedef void __fastcall (__closure *TMessageEvent) (tagMSG &Msg,bool &Handled);

  Msg表示被截获的消息,Handled表示是否处理完成,为TRUE则防止被再次处理,设为FALSE则可以继续处理。

  代码

  //计算程序响应的消息数

  //---------------------------------------------------------------------------

  #ifndef Msg_testH

  #define Msg_testH

  //---------------------------------------------------------------------------

  #include <Classes.hpp>

  #include <Controls.hpp>

  #include <StdCtrls.hpp>

  #include <Forms.hpp>

  //---------------------------------------------------------------------------

  class TForm1 : public TForm

  {

  __published:    // IDE-managed Components

  TLabel *Label1;

  void __fastcall FormCreate(TObject *Sender);

  private:    // User declarations

  //自定义消息响应函数

  void __fastcall AppMessage(tagMSG &MSG,bool &Handled);

  public:        // User declarations

  __fastcall TForm1(TComponent* Owner);

  int Num;

  };

  //---------------------------------------------------------------------------

  extern PACKAGE TForm1 *Form1;

  //---------------------------------------------------------------------------

  #endif

  //---------------------------------------------------------------------------

  #include <vcl.h>

  #pragma hdrstop

  #include "Msg_test.h"

  //---------------------------------------------------------------------------

  #pragma package(smart_init)

  #pragma resource "*.dfm"

  TForm1 *Form1;

  //---------------------------------------------------------------------------

  __fastcall TForm1::TForm1(TComponent* Owner)

  : TForm(Owner)

  {

  Num = 0;

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm1::FormCreate(TObject *Sender)

  {

  //将自定义函数与OnMessage事件联系起来

  Application->OnMessage = AppMessage;

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm1::AppMessage(tagMSG &MSG,bool &Handled)

  {

  Num++;

  Label1->Caption = AnsiString(Num);

  Handled = false;

  }

  二、消息映射

  使用消息映射,一般需要三步:

  (1).声明消息映射表,把某些消息的处理权,交给自己定义的函数

  以一个没有参数的BEGIN_MESSAGE_MAP宏开始,

  以END_MESSAGE_MAP宏结束(唯一参数是组件的父类的名字,通常为TForm)

  在中间插入一个或多个MESSAGE_HANDLER宏,其将一个消息句柄和一个消息处理函数联系在一起。

  MESSAGE_HANDLER(windows消息名,消息结构体名,消息处理函数名)

  (2)声明消息处理函数

  函数名称和参数必须和MESSAGE_HANDLER宏定义的一样

  (3)实现消息处理函数

  与一般类函数差不多,只是在最后加上一条语句,完成VCL对消息的默认处理

  TForm::Dispatch(&Message);

  消息映射

  //---------------------------------------------------------------------------

  #ifndef Unit1H

  #define Unit1H

  //---------------------------------------------------------------------------

  #include <Classes.hpp>

  #include <Controls.hpp>

  #include <StdCtrls.hpp>

  #include <Forms.hpp>

  //---------------------------------------------------------------------------

  class TForm1 : public TForm

  {

  __published:    // IDE-managed Components

  TLabel *Label1;

  private:    // User declarations

  public:        // User declarations

  __fastcall TForm1(TComponent* Owner);

  //自定义消息映射函数

  void __fastcall WMGetMinMaxInfo(TWMGetMinMaxInfo &Msg);

  BEGIN_MESSAGE_MAP

  MESSAGE_HANDLER(WM_GETMINMAXINFO,TWMGetMinMaxInfo,WMGetMinMaxInfo)

  END_MESSAGE_MAP(TForm)

  };

  //---------------------------------------------------------------------------

  extern PACKAGE TForm1 *Form1;

  //---------------------------------------------------------------------------

  #endif

  //---------------------------------------------------------------------------

  #include <vcl.h>

  #pragma hdrstop

  #include "Unit1.h"

  //---------------------------------------------------------------------------

  #pragma package(smart_init)

  #pragma resource "*.dfm"

  TForm1 *Form1;

  //---------------------------------------------------------------------------

  __fastcall TForm1::TForm1(TComponent* Owner)

  : TForm(Owner)

  {

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm1::WMGetMinMaxInfo(TWMGetMinMaxInfo &Msg)

  {

  //当用户单击窗体状态栏上的最大化按钮时,限制窗体的长宽

  Msg.MinMaxInfo->ptMaxSize.x = 600;

  Msg.MinMaxInfo->ptMaxSize.y = 400;

  //设定窗体最大化时,左上角左边为窗体当前位置

  Msg.MinMaxInfo->ptMaxPosition.x = Left;

  Msg.MinMaxInfo->ptMaxPosition.y = Top;

  //当用户用鼠标拖动的方式改变窗体尺寸时,限制其最大值

  Msg.MinMaxInfo->ptMaxTrackSize.x = 600;

  Msg.MinMaxInfo->ptMaxTrackSize.y = 400;

  //当用户用鼠标拖动的方式改变窗体尺寸时,限制其最小值

  Msg.MinMaxInfo->ptMinTrackSize.x = 200;

  Msg.MinMaxInfo->ptMinTrackSize.y = 10;

  //显示当前窗体的尺寸

  Label1->Caption = "Width:" + AnsiString(this->Width)+

  " Height: " + AnsiString(Height);

  TForm::Dispatch(&Msg);

  }

  三、消息映射的深入讨论

  ../include/vcl/sysmac.h中有消息映射的宏定义

  代码

  #define BEGIN_MESSAGE_MAP   virtual void __fastcall Dispatch(void *Message)

  {                                          

  switch  (((PMessage)Message)->Msg)       

  {

  #define VCL_MESSAGE_HANDLER(msg,type,meth)         

  case    msg:                             

  meth(*((type *)Message));              

  break;

  // NOTE: ATL defines a MESSAGE_HANDLER macro which conflicts with VCL's macro. The

  //       VCL macro has been renamed to VCL_MESSAGE_HANDLER. If you are not using ATL,

  //       MESSAGE_HANDLER is defined as in previous versions of BCB.

  //

  #if !defined(USING_ATL) && !defined(USING_ATLVCL) && !defined(INC_ATL_HEADERS)

  #define MESSAGE_HANDLER  VCL_MESSAGE_HANDLER

  #endif // ATL_COMPAT

  #define END_MESSAGE_MAP(base)           default:   

  base::Dispatch(Message);   

  break;                     

  }                                        

  }

  //对与消息映射:

  BEGIN_MESSAGE_MAP

  MESSAGE_HANDLER(WM_GETMINMAXINFO,TWMGetMinMaxInfo,WMGetMinMaxInfo)

  END_MESSAGE_MAP(TForm1)

  //将被扩展为:

  virtual void __fastcall Dispatch(void *Message)

  {

  switch  (((PMessage)Message)->Msg)

  {

  case    msg:

  WMGetMinMaxInfo(*((TWMGetMinMaxInfo*)Message));

  break;

  default:

  TForm1::Dispatch(Message);

  break;

  }

  }

  VCL_MESSAGE_HANDLER写法,是为了调用ATL时,命名不冲突

  四、重载WndProc()函数

  函数原型:

  virtual void __fastcall WndProc(Message::TMessage &Message);

  代码

  //头文件中声明

  void __fastcall WndProc(TMessage &Message);

  //实现文件

  void __fastcall TForm1::WndProc(TMessage &Message)

  {

  if(Message.Msg == WM_GETMINMAXINFO)

  {

  //付给结构体LPMINMAXINFO

  LPMINMAXINFO lpmmi = (LPMINMAXINFO)Message.LParam;

  //当用户单击窗体状态栏上的最大化按钮时,限制窗体的长宽

  lpmmi->ptMaxSize.x = 600;

  lpmmi->ptMaxSize.y = 400;

  //设定窗体最大化时,左上角左边为窗体当前位置

  lpmmi->ptMaxPosition.x = Left;

  lpmmi->ptMaxPosition.y = Top;

  //当用户用鼠标拖动的方式改变窗体尺寸时,限制其最大值

  lpmmi->ptMaxTrackSize.x = 600;

  lpmmi->ptMaxTrackSize.y = 400;

  //当用户用鼠标拖动的方式改变窗体尺寸时,限制其最小值

  lpmmi->ptMinTrackSize.x = 200;

  lpmmi->ptMinTrackSize.y = 100;

  //显示当前窗体的尺寸

  Label1->Caption = "Width:" + AnsiString(this->Width)+

  " Height: " + AnsiString(Height);

  }

  TForm::WndProc(Message);

  }

  五、非标准消息

  1.通知消息(Notification message)

  此消息只发生在一些标准windows控件上

  当一个窗体的子控件发生了一些事情后,他通知给其父窗体的消息

  包括:按钮、编辑框、列表空、label等..

  如:BN_CLICKED 单击按钮

  2.自定义消息

  相比通过改变对象成员的优点:可以不用知道接收者的确切类型,只要知道其窗口句柄;可以广播给多个接受者。

  一般有两种方式:直接定义,WM_USER + XXX 或 WM_APP+XXX 分别为0x0400和0x8000

  或调用API函数RegisterWindowMessage()向系统注册一个
3.发送自定义消息

  向特定窗体发送消息:

  TControl::Perform() 由C++ builder提供

  SendMessage() 和 PostMessage() API函数

  发送广播消息

  TWinControl::Broadcast()  由C++ builder提供

  BroadcastSystemMessage()  API函数

  Perform() 适用于在同一应用程序的不同窗体和控件消息的传递。

  SendMessage() 把消息直接发送给窗口函数(不入队列),等消息被处理后才返回。

  PostMessage() 只是单纯吧消息送到消息队列中,就立刻返回。

  Boradcast() 只能向C++ builder应用程序中的指定窗体上的所有子控件广播消息,无法向其他应用程序广播。

  BroadcastSystemMessage() 可以向任意的应用程序或者组件广播消息。

  代码

  //窗体1(四个按钮)

  //---------------------------------------------------------------------------

  #ifndef Unit1H

  #define Unit1H

  //---------------------------------------------------------------------------

  #include <Classes.hpp>

  #include <Controls.hpp>

  #include <StdCtrls.hpp>

  #include <Forms.hpp>

  #include "Unit2.h"

  //---------------------------------------------------------------------------

  class TForm1 : public TForm

  {

  __published:    // IDE-managed Components

  TButton *Button1;

  TButton *Button2;

  TButton *Button3;

  TButton *Button4;

  void __fastcall Button1Click(TObject *Sender);

  void __fastcall Button2Click(TObject *Sender);

  void __fastcall Button3Click(TObject *Sender);

  void __fastcall Button4Click(TObject *Sender);

  private:    // User declarations

  public:        // User declarations

  __fastcall TForm1(TComponent* Owner);

  };

  //---------------------------------------------------------------------------

  extern PACKAGE TForm1 *Form1;

  //---------------------------------------------------------------------------

  #endif

  //---------------------------------------------------------------------------

  #include <vcl.h>

  #pragma hdrstop

  #include "Unit1.h"

  //---------------------------------------------------------------------------

  #pragma package(smart_init)

  #pragma resource "*.dfm"

  TForm1 *Form1;

  //---------------------------------------------------------------------------

  __fastcall TForm1::TForm1(TComponent* Owner)

  : TForm(Owner)

  {

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm1::Button1Click(TObject *Sender)

  {

  Form2->Perform(WM_CLOSE,0,0);

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm1::Button2Click(TObject *Sender)

  {

  SendMessage(Form2->Handle,WM_CLOSE,0,0);

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm1::Button3Click(TObject *Sender)

  {

  PostMessage(Form2->Handle,WM_CLOSE,0,0);

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm1::Button4Click(TObject *Sender)

  {

  //向窗体Form2的子控件广播WM_LBUTTONDOWN消息

  TMessage M;

  M.Msg = WM_LBUTTONDOWN;

  Form2->Broadcast(&M);

  }

  //---------------------------------------------------------------------------

  //窗体2(两个panel)

  //---------------------------------------------------------------------------

  #ifndef Unit2H

  #define Unit2H

  //---------------------------------------------------------------------------

  #include <Classes.hpp>

  #include <Controls.hpp>

  #include <StdCtrls.hpp>

  #include <Forms.hpp>

  #include <ExtCtrls.hpp>

  //---------------------------------------------------------------------------

  class TForm2 : public TForm

  {

  __published:    // IDE-managed Components

  TPanel *Panel1;

  TPanel *Panel2;

  void __fastcall Panel1MouseDown(TObject *Sender, TMouseButton Button,

  TShiftState Shift, int X, int Y);

  void __fastcall Panel2MouseDown(TObject *Sender, TMouseButton Button,

  TShiftState Shift, int X, int Y);

  private:    // User declarations

  public:        // User declarations

  __fastcall TForm2(TComponent* Owner);

  };

  //---------------------------------------------------------------------------

  extern PACKAGE TForm2 *Form2;

  //---------------------------------------------------------------------------

  #endif

  //---------------------------------------------------------------------------

  #include <vcl.h>

  #pragma hdrstop

  #include "Unit2.h"

  //---------------------------------------------------------------------------

  #pragma package(smart_init)

  #pragma resource "*.dfm"

  TForm2 *Form2;

  //---------------------------------------------------------------------------

  __fastcall TForm2::TForm2(TComponent* Owner)

  : TForm(Owner)

  {

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm2::Panel1MouseDown(TObject *Sender,

  TMouseButton Button, TShiftState Shift, int X, int Y)

  {

  Panel1->Caption = "Down";

  }

  //---------------------------------------------------------------------------

  void __fastcall TForm2::Panel2MouseDown(TObject *Sender,

  TMouseButton Button, TShiftState Shift, int X, int Y)

  {

  Panel2->Caption = "Down";

  }

  //---------------------------------------------------------------------------

  六

  若自定义消息想带参数,可用LParam和WParam参数

  更多可自定义结构体

  LPARAM+WPARAM能放下就放,放不下就传指针. SENDMESSAGE可以传局部变量的指针,POSTMESSAGE只能传 全局/局部静态/堆上的 变量的指针.

  如:映射到TMessage结构体中,然后取出

  void __fastcall myMessage(TMessage &Msg)

  {

  int i = Msg.WParam;

  }

文章内容来源于网络,不代表本站立场,若侵犯到您的权益,可联系我们删除。(本站为非盈利性质网站) 联系邮箱:9145908@qq.com