C++builder 消息的运用

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值