http://tech.e800.com.cn/articles/2010/17/1262842530085_1.html
一、TApplication的OnMessage事件
OnMessage事件只处理消息队列中的消息,SendMessage()发送的消息不会被截获。
任何窗体接收到一个windows消息,都会触发一次此事件
函数原型:
typedef void __fastcall (__closure TMessageEvent) (tagMSG &Msg,bool &Handled);
Msg表示被截获的消息,Handled表示是否处理完成,为TRUE则防止被再次处理,设为FALSE则可以继续处理。
代码//计算程序响应的消息数
//---------------------------------------------------------------------------
#ifndef Msg_testH
#defineMsg_testH
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
//---------------------------------------------------------------------------
classTForm1 :publicTForm
{
__published://IDE-managed Components
TLabelLabel1;
void__fastcall FormCreate(TObjectSender);
private://User declarations
//自定义消息响应函数
void__fastcall AppMessage(tagMSG&MSG,bool&Handled);
public://User declarations
__fastcall TForm1(TComponentOwner);
intNum;
};
//---------------------------------------------------------------------------
externPACKAGE TForm1Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"Msg_test.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource ".dfm"
TForm1Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
: TForm(Owner)
{
Num=0;
}
//---------------------------------------------------------------------------
void__fastcall TForm1::FormCreate(TObjectSender)
{
//将自定义函数与OnMessage事件联系起来
Application->OnMessage=AppMessage;
}
//---------------------------------------------------------------------------
void__fastcall TForm1::AppMessage(tagMSG&MSG,bool&Handled)
{
Num++;
Label1->Caption=AnsiString(Num);
Handled=false;
}
//计算程序响应的消息数
//---------------------------------------------------------------------------
#ifndef Msg_testH
#defineMsg_testH
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
//---------------------------------------------------------------------------
classTForm1 :publicTForm
{
__published://IDE-managed Components
TLabelLabel1;
void__fastcall FormCreate(TObjectSender);
private://User declarations
//自定义消息响应函数
void__fastcall AppMessage(tagMSG&MSG,bool&Handled);
public://User declarations
__fastcall TForm1(TComponentOwner);
intNum;
};
//---------------------------------------------------------------------------
externPACKAGE TForm1Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"Msg_test.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource ".dfm"
TForm1Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
: 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
#defineUnit1H
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
//---------------------------------------------------------------------------
classTForm1 :publicTForm
{
__published://IDE-managed Components
TLabelLabel1;
private://User declarations
public://User declarations
__fastcall TForm1(TComponentOwner);
//自定义消息映射函数
void__fastcall WMGetMinMaxInfo(TWMGetMinMaxInfo&Msg);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_GETMINMAXINFO,TWMGetMinMaxInfo,WMGetMinMaxInfo)
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
externPACKAGE TForm1Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"Unit1.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource ".dfm"
TForm1Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
: 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);
}
//---------------------------------------------------------------------------
#ifndef Unit1H
#defineUnit1H
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
//---------------------------------------------------------------------------
classTForm1 :publicTForm
{
__published://IDE-managed Components
TLabelLabel1;
private://User declarations
public://User declarations
__fastcall TForm1(TComponentOwner);
//自定义消息映射函数
void__fastcall WMGetMinMaxInfo(TWMGetMinMaxInfo&Msg);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_GETMINMAXINFO,TWMGetMinMaxInfo,WMGetMinMaxInfo)
END_MESSAGE_MAP(TForm)
};
//---------------------------------------------------------------------------
externPACKAGE TForm1Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"Unit1.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource ".dfm"
TForm1Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
: 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中有消息映射的宏定义
代码#defineBEGIN_MESSAGE_MAP virtual void __fastcall Dispatch(void Message)
{
switch(((PMessage)Message)->Msg)
{
#defineVCL_MESSAGE_HANDLER(msg,type,meth)
casemsg:
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)
#defineMESSAGE_HANDLER VCL_MESSAGE_HANDLER
#endif//ATL_COMPAT
#defineEND_MESSAGE_MAP(base) default:
base::Dispatch(Message);
break;
}
}
//对与消息映射:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_GETMINMAXINFO,TWMGetMinMaxInfo,WMGetMinMaxInfo)
END_MESSAGE_MAP(TForm1)
//将被扩展为:
virtualvoid__fastcall Dispatch(voidMessage)
{
switch(((PMessage)Message)->Msg)
{
casemsg:
WMGetMinMaxInfo(((TWMGetMinMaxInfo)Message));
break;
default:
TForm1::Dispatch(Message);
break;
}
}
#defineBEGIN_MESSAGE_MAP virtual void __fastcall Dispatch(void Message)
{
switch(((PMessage)Message)->Msg)
{
#defineVCL_MESSAGE_HANDLER(msg,type,meth)
casemsg:
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)
#defineMESSAGE_HANDLER VCL_MESSAGE_HANDLER
#endif//ATL_COMPAT
#defineEND_MESSAGE_MAP(base) default:
base::Dispatch(Message);
break;
}
}
//对与消息映射:
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_GETMINMAXINFO,TWMGetMinMaxInfo,WMGetMinMaxInfo)
END_MESSAGE_MAP(TForm1)
//将被扩展为:
virtualvoid__fastcall Dispatch(voidMessage)
{
switch(((PMessage)Message)->Msg)
{
casemsg:
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);
}
//头文件中声明
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
#defineUnit1H
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
#include"Unit2.h"
//---------------------------------------------------------------------------
classTForm1 :publicTForm
{
__published://IDE-managed Components
TButtonButton1;
TButtonButton2;
TButtonButton3;
TButtonButton4;
void__fastcall Button1Click(TObjectSender);
void__fastcall Button2Click(TObjectSender);
void__fastcall Button3Click(TObjectSender);
void__fastcall Button4Click(TObjectSender);
private://User declarations
public://User declarations
__fastcall TForm1(TComponentOwner);
};
//---------------------------------------------------------------------------
externPACKAGE TForm1Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"Unit1.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource ".dfm"
TForm1Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void__fastcall TForm1::Button1Click(TObjectSender)
{
Form2->Perform(WM_CLOSE,0,0);
}
//---------------------------------------------------------------------------
void__fastcall TForm1::Button2Click(TObjectSender)
{
SendMessage(Form2->Handle,WM_CLOSE,0,0);
}
//---------------------------------------------------------------------------
void__fastcall TForm1::Button3Click(TObjectSender)
{
PostMessage(Form2->Handle,WM_CLOSE,0,0);
}
//---------------------------------------------------------------------------
void__fastcall TForm1::Button4Click(TObjectSender)
{
//向窗体Form2的子控件广播WM_LBUTTONDOWN消息
TMessage M;
M.Msg=WM_LBUTTONDOWN;
Form2->Broadcast(&M);
}
//---------------------------------------------------------------------------
//窗体2(两个panel)
//---------------------------------------------------------------------------
#ifndef Unit2H
#defineUnit2H
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
#include<ExtCtrls.hpp>
//---------------------------------------------------------------------------
classTForm2 :publicTForm
{
__published://IDE-managed Components
TPanelPanel1;
TPanelPanel2;
void__fastcall Panel1MouseDown(TObjectSender, TMouseButton Button,
TShiftState Shift,intX,intY);
void__fastcall Panel2MouseDown(TObjectSender, TMouseButton Button,
TShiftState Shift,intX,intY);
private://User declarations
public://User declarations
__fastcall TForm2(TComponentOwner);
};
//---------------------------------------------------------------------------
externPACKAGE TForm2Form2;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"Unit2.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource ".dfm"
TForm2Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponentOwner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void__fastcall TForm2::Panel1MouseDown(TObjectSender,
TMouseButton Button, TShiftState Shift,intX,intY)
{
Panel1->Caption="Down";
}
//---------------------------------------------------------------------------
void__fastcall TForm2::Panel2MouseDown(TObjectSender,
TMouseButton Button, TShiftState Shift,intX,intY)
{
Panel2->Caption="Down";
}
//---------------------------------------------------------------------------
//窗体1(四个按钮)
//---------------------------------------------------------------------------
#ifndef Unit1H
#defineUnit1H
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
#include"Unit2.h"
//---------------------------------------------------------------------------
classTForm1 :publicTForm
{
__published://IDE-managed Components
TButtonButton1;
TButtonButton2;
TButtonButton3;
TButtonButton4;
void__fastcall Button1Click(TObjectSender);
void__fastcall Button2Click(TObjectSender);
void__fastcall Button3Click(TObjectSender);
void__fastcall Button4Click(TObjectSender);
private://User declarations
public://User declarations
__fastcall TForm1(TComponentOwner);
};
//---------------------------------------------------------------------------
externPACKAGE TForm1Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"Unit1.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource ".dfm"
TForm1Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponentOwner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void__fastcall TForm1::Button1Click(TObjectSender)
{
Form2->Perform(WM_CLOSE,0,0);
}
//---------------------------------------------------------------------------
void__fastcall TForm1::Button2Click(TObjectSender)
{
SendMessage(Form2->Handle,WM_CLOSE,0,0);
}
//---------------------------------------------------------------------------
void__fastcall TForm1::Button3Click(TObjectSender)
{
PostMessage(Form2->Handle,WM_CLOSE,0,0);
}
//---------------------------------------------------------------------------
void__fastcall TForm1::Button4Click(TObjectSender)
{
//向窗体Form2的子控件广播WM_LBUTTONDOWN消息
TMessage M;
M.Msg=WM_LBUTTONDOWN;
Form2->Broadcast(&M);
}
//---------------------------------------------------------------------------
//窗体2(两个panel)
//---------------------------------------------------------------------------
#ifndef Unit2H
#defineUnit2H
//---------------------------------------------------------------------------
#include<Classes.hpp>
#include<Controls.hpp>
#include<StdCtrls.hpp>
#include<Forms.hpp>
#include<ExtCtrls.hpp>
//---------------------------------------------------------------------------
classTForm2 :publicTForm
{
__published://IDE-managed Components
TPanelPanel1;
TPanelPanel2;
void__fastcall Panel1MouseDown(TObjectSender, TMouseButton Button,
TShiftState Shift,intX,intY);
void__fastcall Panel2MouseDown(TObjectSender, TMouseButton Button,
TShiftState Shift,intX,intY);
private://User declarations
public://User declarations
__fastcall TForm2(TComponentOwner);
};
//---------------------------------------------------------------------------
externPACKAGE TForm2Form2;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include<vcl.h>
#pragmahdrstop
#include"Unit2.h"
//---------------------------------------------------------------------------
#pragmapackage(smart_init)
#pragmaresource ".dfm"
TForm2Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponentOwner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void__fastcall TForm2::Panel1MouseDown(TObjectSender,
TMouseButton Button, TShiftState Shift,intX,intY)
{
Panel1->Caption="Down";
}
//---------------------------------------------------------------------------
void__fastcall TForm2::Panel2MouseDown(TObjectSender,
TMouseButton Button, TShiftState Shift,intX,intY)
{
Panel2->Caption="Down";
}
//---------------------------------------------------------------------------
六
若自定义消息想带参数,可用LParam和WParam参数
更多可自定义结构体
LPARAM+WPARAM能放下就放,放不下就传指针. SENDMESSAGE可以传局部变量的指针,POSTMESSAGE只能传 全局/局部静态/堆上的 变量的指针.
如:映射到TMessage结构体中,然后取出
void __fastcall myMessage(TMessage &Msg)
{
int i = Msg.WParam;
}
原文链接: https://www.cnblogs.com/chulia20002001/archive/2011/05/05/2037812.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/24974
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!