關於捕獲VCL沒有處理的Windows訊息 (轉)

worldblog發表於2007-12-10
關於捕獲VCL沒有處理的Windows訊息 (轉)[@more@]

 

  對於C++ Builder的員來說,VCL以其靈活、高效的特點令人喜愛。因為VCL是在 的基礎上進行了封裝,同時捨棄了一些不常用的功能,所以,VCL在功能上是Windows API 的子集。VCL提供了對大多數Windows訊息的處理機制,但是對於沒有處理的Windows訊息呢,在需要是如何捕獲呢?C++ Builder採用了訊息對映標機制,透過訊息對映表將特定的Windows訊息於程式碼中的聯絡起來,當視窗捕獲到訊息時就會這個函式。
   C++ Builder訊息對映表定義形式如下:
   BEGIN_MESSAGE_MAP
 MESSAGE_HANDLER( , , )
  END_MESSAGE_MAP(ClassName)
 其中:
  BEGIN_MESSAGE_MAP:訊息對映定義起始語句
   MESSAGE_HANDLER:訊息處理定義
  END_MESSAGE_MAP:訊息對映定義結束語句
  ClassName:是要接受訊息的類名
  message:是要截獲的Windows訊息
  message handler:訊息處理函式名稱
  message structure:是用於傳遞給VCL訊息的結構名稱,此結構裡包含有處理訊息時所需的全部引數,不同的訊息所對應的訊息結構是不同的。
  由於每一個VCL(無論是窗體還是按鈕)都可以獨立的接收Windows訊息,並且進行獨立的響應,所以一定要注意訊息定一種的ClassName引數。
  現在舉例說明訊息定義、傳遞的應用。現在一個窗體FormMain,和2個TperformanceGraph控制元件(不能響應滑鼠事件),現在我要對2個TperformanceGraph控制元件定義滑鼠單擊事件,對FormMain也重定義滑鼠單擊事件,過程如下(假定工程為Message.bpr,程式檔案為main.cpp、main.h):
  如下:
//----main.h--------------------------------------------------------------
#ifndef mainH
#define mainH
//----------------------------------------------------------

#include
#include
#include
#include
#include "PERFGRAP.h"
//-----------------------------------------------------------
class TFormMain : public TForm
{
__published: // -managed Components
//----2個標準TperformanceGraph控制元件
  TPerformanceGraph *PerformanceGraph1;
  TPerformanceGraph *PerformanceGraph2;
  TEdit *Edit2;
  TEdit *Edit1;
  void __fastcall FormCreate(T *Sender);
private: // User declarations
//----自定義的訊息處理函式,其中MESSAGE可以不寫
  MESSAGE void __fastcall LButtonDown(TMessage &message);
//----定義的函式(處理訊息,具體使用見.cpp檔案)
  void __fastcall MyWndProc1(TMessage &message);
  void __fastcall MyWndProc2(TMessage &message);
//----函式指標,用來儲存2個TperformanceGraph控制元件的訊息處理函式的指標
  TWndMethod OldWndProc1 , OldWndProc2;
public: // User declarations
  __fastcall TFormMain(TComponent* Owner);
//----窗體的訊息定義
  BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(WM_LBUTTONDOWN , TMessage , LButtonDown)
  END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
extern PACKAGE TFormMain *FormMain;
//---------------------------------------------------------------------------
#endif

//----main.cpp------------------------------------------------------------
#include
#pragma hdrstop
#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "PERFGRAP"
#pragma re "*.dfm"
TFormMain *FormMain;
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
  : TForm(Owner)
{}
//---------------------------------------------------------------------------
void __fastcall TFormMain::LButtonDown(TMessage &message)
{
//----如果滑鼠在窗體內(控制元件外)被單擊,則此事件被啟用
  if(GetAsyncKeyState(VK_LBUTTON) < 0)
  {
Application->MessageBoxA("FoGet Messsge" , "Message" , MB_OK);
//----向Edit2傳送滑鼠訊息,則Edit2將產生單擊獲得焦點的現象
SendMessage(FormMain->Edit2->Handle ,
  message.Msg ,
  message.WParam ,
  message.LParam);
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormCreate(TObject *Sender)
{
 //----替換2個TperformanceGraph控制元件的訊息處理函式控制程式碼
  OldWndProc1 = PerformanceGraph1->WindowProc;
  OldWndProc2 = PerformanceGraph2->WindowProc;
  PerformanceGraph1->WindowProc = MyWndProc1;
  PerformanceGraph2->WindowProc = MyWndProc2;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::MyWndProc1(TMessage &message)
{
  if (message.Msg == WM_LBUTTONDOWN)
//----如果訊息是“滑鼠單擊訊息”,則顯示資訊
ShowMessage("PerformanceGraph1 Get Message ");
  else 
//----如果訊息是其他訊息,則交給控制元件原來的處理
OldWndProc1(message);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::MyWndProc2(TMessage &message)
{
  if (message.Msg == WM_LBUTTONDOWN) 
ShowMessage("PerformanceGraph 2 get Message");
  else 
OldWndProc2(message);
}
 如果在TFormMain::FormCreate()函式中加入以下兩句語句:
 OldWndProc3 = FormMain->WindowProc;
FormMain->WindowProc = MyWndProc3;
再新增函式:
void __fastcall TFormMain::MyWndProc3(TMessage &message)
{
  if (message.Msg == WM_LBUTTONDOWN)
//----如果訊息是“滑鼠單擊訊息”,則顯示資訊
ShowMessage(“FormMain Get the Message ");
  else 
//----如果訊息是其他訊息,則交給控制元件原來的處理
OldWndProc1(message);
}
則把FormMain的滑鼠訊息響應函式進行了改裝,此時窗體就會截獲滑鼠訊息,而2個TperformanceGraph控制元件將不會得到訊息。這是因為窗體將先於控制元件得到訊息。
  從上面的例子可以看出:
1、 窗體將先於控制元件得到訊息;
2、 對於響應某一訊息的控制元件,可以用SendMessage想起傳送訊息;
3、 對於不響應某一訊息的控制元件,可以用過載其WindowProc屬性獲得你想要的效果。
  實際上,掌握了利用Windows的訊息傳遞機制才是掌握C++ Builder的第二階段,任重而道遠。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990910/,如需轉載,請註明出處,否則將追究法律責任。

相關文章