深入VCL领略BCB的动静机制1
本文所谈及的技能内容都来自于Internet的果真信息。由CKER在闲暇之际整理后,贴出来以飴网友,暂时妄称原创。
『每次在海外网站上找到出色文章的时候,心中城市暗自感叹为什么在中文网站难以觅得这类文章呢?其实原因各人都大白。』
时至今天,进修Windows编程的兄弟们都知道动静机制的重要性。所以领略动静机制也成了不行或缺的作业。
各人都知道,Borland的C++ Builder以及Delphi的焦点是VCL。作为Win32平台上的开拓东西,封装Windows的动静机制虽然也是必不行少的。
那么,在C++ Builder中处理惩罚动静的要领有哪些呢?它们之间的区别又在那边?假如您很清楚这些,呵呵,对不起啦,请关掉这个窗口。
假如不清楚那就和我一起深入VCL的源码看个毕竟吧。『注:BCB只有Professional和Enterprise版本才带有VCL源码。虽然,大伙的版本都有源码的。我没猜错吧 :-)<CKER用的是BCB5>』
要领1。利用动静映射(Message Map)重载TObject的Dispatch虚成员函数
这个要领各人用的许多。形式如下
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER( … …)
END_MESSAGE_MAP( …)
但这几句话实在太突兀,C++尺度中没有这样的界说。不消讲,这显然又是宏界说。它们到底怎么来的呢?CKER第一次见到它们的时候,百思不得其解。嘿嘿,不深入VCL,怎么大概领略?
在\Borland\CBuilder5\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.
file://
#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
VCL_MESSAGE_HANDLER(WM_PAINT,TMessage,OnPaint)
END_MESSAGE_MAP(TForm1)
在预编译时,就被展开成如下的代码
virtual void __fastcall Dispatch(void *Message)
{
switch (((PMessage)Message)->Msg)
{
case WM_PAINT:
OnPaint(*((TMessage *)Message)); //动静响应句柄,也就是响应动静的成员函数,在Form1中界说
break;
default:
Form1::Dispatch(Message);
break;
}
}
这样就很顺眼了,对吧。对这种要领有两点要表明一下:
1。virtual void __fastcall Dispatch(void *Message) 这个虚要领的界说最早可以在TObject的界说中找到。打开
BCB的辅佐,查找TForm的Method(要领),你会发明这里很清楚的写着Dispatch要领担任自TObject。假如您体贴VCL的担任机制的话,您会发明TObject是所有VCL工具的基类。TObject的抽象凝结了Borland的工程师们的心血。假如有乐趣。您应该好好查察一下TObject的界说。
很显然,所有Tobject的子类都可以重载基类的Dispatch要领,来实现本身的动静挪用。假如Dispatch要领找不到此动静的界说,会将此动静交由TObject::DefaultHandler要领来处理惩罚。抽象基类TObject的DefaultHandler要领实际上是空的。同样要由担任子类重载实现它们本身的动静处理惩罚进程。
2。许多时候,我见到的第二行是这样写的:
MESSAGE_HANDLER(WM_PAINT,TMessage,OnPaint)
在这里,您可以很清楚的看到几行注解,意思是ATL中同样包括了一个MESSAGE_HANDLER的宏界说,这与VCL产生了斗嘴。为了办理这个问题,Borland改用VCL_MESSAGE_HANDLER这样的写法。
当您没有利用ATL的时候,MESSAGE_HANDLER将转换成VCL_MESSAGE_HANDLER。但假如您利用了ATL的话,就会有问题。所以我发起您始终利用VCL_MESSAGE_HANDLER的写法,以免呈现问题。