用戶: 密碼:     忘記密碼 | 會員註冊
  

C++ builder消息的運用

8.5
出處:2345軟件大全 時間:2011-06-27 人氣:2646

核心提示:OnMessage事件只處理消息隊列中的消息,SendMessage()發送的消息不會被截獲。

  一、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;

  }