深入VCL理解BCB的消息机制1

2016-02-19 15:32 13 1 收藏

岁数大了,QQ也不闪了,微信也不响了,电话也不来了,但是图老师依旧坚持为大家推荐最精彩的内容,下面为大家精心准备的深入VCL理解BCB的消息机制1,希望大家看完后能赶快学习起来。

【 tulaoshi.com - 编程语言 】

  本文所谈及的技术内容都来自于Internet的公开信息。由CKER在闲暇之际整理后,贴出来以飴网友,姑且妄称原创。

  『每次在国外网站上找到精彩文章的时候,心中都会暗自叹息为什么在中文网站难以觅得这类文章呢?其实原因大家都明白。』

  时至今日,学习Windows编程的兄弟们都知道消息机制的重要性。所以理解消息机制也成了不可或缺的功课。

  大家都知道,Borland的C++ Builder以及Delphi的核心是VCL。作为Win32平台上的开发工具,封装Windows的消息机制当然也是必不可少的。

  那么,在C++ Builder中处理消息的方法有哪些呢?它们之间的区别又在哪里?如果您很清楚这些,呵呵,对不起啦,请关掉这个窗口。

  如果不清楚那就和我一起深入VCL的源码看个究竟吧。『注:BCB只有Professional和Enterprise版本才带有VCL源码。当然,大伙的版本都有源码的。我没猜错吧 :-)CKER用的是BCB5』

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  方法1。使用消息映射(Message Map)重载TObject的Dispatch虚成员函数

  这个方法大家用的很多。形式如下

  

BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER( )
END_MESSAGE_MAP( )

  但这几句话实在太突兀,C++标准中没有这样的定义。不用讲,这显然又是宏定义。它们到底怎么来的呢?CKER第一次见到它们的时候,百思不得其解。嘿嘿,不深入VCL,怎么可能理解?

  在BorlandCBuilder5IncludeVcl找到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这样的写法。

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  当您没有使用ATL的时候,MESSAGE_HANDLER将转换成VCL_MESSAGE_HANDLER。但如果您使用了ATL的话,就会有问题。所以我建议您始终使用VCL_MESSAGE_HANDLER的写法,以免出现问题。

来源:https://www.tulaoshi.com/n/20160219/1609863.html

延伸阅读
递归:一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。本案例很清楚的说明了递归是如何将一个复杂的问题转化为规模较小的问题来解决的。下面通过一个小例子来说明递归的原理。 代码如下: /** * @fileName Test.java * @description 递归学...
以下不完整例子为生成一个TMemo的派生类及动态地创建该VCL控件。 Class TMemoEx : public TMemo { . . } extern TMemoEx memoex; Class TForm1 : Class TForm { public: TMemoEx *MemoEx; . . } void _fastcall TForm1::FormShow(TObject *Sender) ...
一. 继承基础知识 为了提高软件模块的可复用性和可扩充性,以便提高软件的开发效率,我们总是希望能够利用前人或自己以前的开发成果,同时又希望在自己的开发过程中能够有足够的灵活性,不拘泥于复用的模块。C#这种完全面向对象的程序设计语言提供了两个重要的特性--继承性inheritance 和多态性polymorphism。 继承是面向对象程...
Java容器类包含List、ArrayList、Vector及map、HashTable、HashMap   ArrayList和HashMap是异步的,Vector和HashTable是同步的,所以Vector和HashTable是线程安全的,而ArrayList和HashMap并不是线程安全的。因为同步需要花费机器时间,所以Vector和HashTable的执行效率要低于ArrayList和HashMap。 Collection ├List  &nbs...
标签: 服务器
Linux系统进程深入理解   1. 什么是进程 进程是处于执行期的程序以及它所包含的所有资源的总称,包括虚拟处理器,虚拟空间,寄存器,堆栈,全局数据段等。 在Linux中,每个进程在创建时都会被分配一个数据结构,称为进程控制块(Process Control Block,简称PCB)。PCB中包含了很多重要的信息,供系统调度和进程本身执行使...

经验教程

645

收藏

78
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部