C Builder中消息处理过程及应用
2008-02-23 05:26:00来源:互联网 阅读 ()
尽管C Builder的VCL控件封装了大多数常用的消息,C Builder所提供的事件处理能力也具备了相当程度的完备性,但当处理C Builder 未定义的Windows消息或自定义消息时,掌控C Builder 的内部消息处理机制还是十分必要的。下面,从Windows 操作系统消息驱动机制开始,进而探讨C Builder的VCL控件中消息的封装、传递和处理机制,最后以新增消息处理过程的应用实例作为对所讲内容的验证和实践。
一、Windows 消息驱动机制
Windows是以消息驱动的操作系统,Windows 消息提供了应用程式和应用程式连同应用程式和Windows系统之间进行通讯的手段。
Windows 中有一个系统消息队列,对于每一个正在执行的Windows应用程式,系统为其建立一个“消息队列”,即应用程式队列,用来存放该程式可能创建的各种窗口的消息。应用程式中含有一段称作“消息循环”的代码,用来从消息队列中检索这些消息并把他们分发到相应的窗口函数中。
消息循环代码是应用程式中主函数winmain ( )中类似如下的程式段:
while(GetMessage(&&msg,NULL,NULL,NULL))
{ //从消息队列中取得消息
TranslateMessage(&&msg);
//检索并生成字符消息WM_CHAR
DispatchMessage(&&msg);
//将消息发送给相应的窗口函数
}
由此可见,所谓“消息循环”,实际是程式循环。
Windows 应用程式创建的每个窗口都在系统核心注册一个相应的窗口函数,窗口函数程式代码形式上是个巨大的switch 语句,用以处理由消息循环发送到该窗口的消息,窗口函数由Windows 采用消息驱动的形式直接调用,而不是由应用程式显示调用的,窗口函数处理完消息后又将控制权返回给Windows。
系统消息队列、应用程式队列、消息循环和窗口函数之间的关系如图1所示。
二、C Builder 中的消息处理
有了以上Windows 系统消息驱动模式程式设计的认识,下面分析一下C Builder中消息处理是如何封装、实现的。
Windows 程式框架,包括一些初始化、消息循环代码等,在类 Application中封装、实现。每一个用C Builder 编写的Windows GUI 应用程式,大部分缺省生成如下代码:
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
//Windows 应用程式主函数
{
try
{
Application-〉Initialize();//作初始化
Application-〉CreateForm(__classid(TForm1), &&Form1);
Application-〉Run();
//其中包含消息循环
}
catch (Exception &&exception) //例外处理
{
Application-〉ShowException(&&exception);
}
return 0;
}
对于消息处理,C Builder采用基于控件(component)的程式设计模式,每种控件都继承一套完整的消息派送体系。其实现方法如下: 他为每一种类型的控件都注册一个名为 MainWndProc 的方法函数作为窗口函数,接受“消息循环”派送来的消息,他是个非虚拟方法,不对任何特定消息作特别处理,他仅仅调用 WndProc 方法函数,并作一些例外处理。不同控件对消息处理的定制发生在WndProc 方法中,因为他是个虚拟方法,每一种控件能够通过覆盖他来适应特别的情况。WndProc 方法检查不同的条件,作不同的处理,从而能够滤掉不希望处理的各种消息。例如:当控件正被拖动时,应忽略键盘事件,所以在Twincontrol 类的WndProc 方法中,有判断当控件不是被拖放状态、才继续传递键盘消息这样功能的代码。最终,WndProc 调用 Dispatch 方法,他是个从所用控件的起始祖先Tobject 继承而来的虚拟方法,他确定调用哪个方法处理传来的消息。Dispatch 使用消息结构(Tmessage)中的 msg 成员变量确定如何处理一个特定的消息,假如控件定义了处理这一消息的函数,则调用他,否则,就逐级向上追溯,看祖先类是否定义此类的处理方法,直到起始祖先类(Tobject)。假如都没有定义处理方法,则调用缺省的处理方法(DefaultHandler)。
以上是消息在控件中的传递过程,INPRISE公司为方便用户,对消息处理作了进一步的封装,把常用的消息封装成相应的事件属性,这样编程者完全不用考虑消息细节,只要编写事件处理方法,并给事件属性赋值即可。
消息在函数之间的传递关系如表1所示。
三、应用实例
下面以增加新的自定义消息处理过程为例,对以上所述内容做进一步的说明。
通过以上分析我们知道,每一条消息的具体处理过程,是在 Dispatch 中派发完成的,因此增加新的消息, 只要覆盖虚拟函数 Dispatch 即可。
C Builder为了方便地处理消息,定义了以下三个处理消息的宏:
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(msg,type,meth)
END_MESSAGE_MAP(base)
定义如下:
#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;
#define END_MESSAGE_MAP(base) default:
base::Dispatch(Message);
break;
}
}
我们只需在控件类或自定义控件类的public节,依次写入三个宏即可,其中宏VCL_MESSAGE_HANDLER能够根据处理消息的条数而出现多次。宏展开后,即生成一个新的Dispatch 函数,他先判断处理用户定义消息,若是其他消息,则传递至父类的Dispatch 函数处理,从而完成自定义消息的处理并确保原来消息处理体系的完整性.
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash