Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > C/C++ > WINX的消息分派机制(续2)
【标  题】:WINX的消息分派机制(续2)
【关键字】:WINX
【来  源】:http://blog.csdn.net/xushiweizh/archive/2006/11/05/1368098.aspx

WINX的消息分派机制(续2)

Your Ad Here  我们继续Inside WINX's Message Dispatch。现在开始我们进入了最为关键的部分——WINX是怎么进行消息分派的。

从原理上来讲,WINX的消息分派函数(DispatchMessage)其实与上一篇:《WINX的消息分派机制(续)》中的并无多大的不同,只不过更加智能而已。其中最为关键的是,WINX引入了一种技巧,它可以在编译期判断一个函数是否被重载。简单来说,WINX的消息分派伪代码如下:

template <class T>
class WindowMessage
{
 ...

 BOOL DispatchMessage(
   HWND hWnd, UINT message,
   WPARAM wParam , LPARAM lParam, LRESULT& lResult)
 {
  T* pThis = static_cast<T*>(this);
  if (派生类重载了OnPaint && message == WM_PAINT)
    pThis->OnPaint(hWnd);
  else if (派生类重载了OnKeyDown && message == WM_KEYDOWN)
    pThis->OnKeyDown(hWnd, wParam, lParam);
  else if (...)
    ...
  else
    return FALSE;
  return TRUE;
 }
};

简单看一个实际的例子,这样做的好处就很明了了。设想WindowMessage的派生类只重载了OnPaint,那么WindowMessage类看起来是这样的:

template <class T>
class WindowMessage
{
 ...

 BOOL DispatchMessage(
   HWND hWnd, UINT message,
   WPARAM wParam , LPARAM lParam, LRESULT& lResult)
 {
  T* pThis = static_cast<T*>(this);
  if (true && message == WM_PAINT)
    pThis->OnPaint(hWnd);
  else if (false && message == WM_KEYDOWN)
    pThis->OnKeyDown(hWnd, wParam, lParam);
  else if (...)
    ...
  else
    return FALSE;
  return TRUE;
 }
};

并最终被编译器优化为:

template <class T>
class WindowMessage
{
 ...

 BOOL DispatchMessage(
   HWND hWnd, UINT message,
   WPARAM wParam , LPARAM lParam, LRESULT& lResult)
 {
  T* pThis = static_cast<T*>(this);
  if (message == WM_PAINT)
    pThis->OnPaint(hWnd);
  else
    return FALSE;
  return TRUE;
 }
};

特别地,如果WindowMessage派生类没有响应任何消息,则优化后DispatchMessage为一个空函数,如下:

template <class T>
class WindowMessage
{
 ...

 BOOL DispatchMessage(
   HWND hWnd, UINT message,
   WPARAM wParam , LPARAM lParam, LRESULT& lResult)
 {
  return FALSE;
 }
};

这就是WINX的消息分派机制为何比MFC、WTL以及其他任何界面库高效(无论是编译后的代码尺寸上,还是执行效率上)的原因。

好了,现在该是解释WINX如何做到这一点——检测派生类是否重载某个函数的时候了。我们假设,基类(名为Base)中有一个成员函数Func(假设有两个参数),现在有另一个成员函数Caller希望根据派生类是否重载Func来做事情。如下:

template <class T>
class Base
{
 RetType Func(ArgType1 arg1, ArgType2 arg2) { ... }
 void Caller() {
  if (派生类重载了Func) { ... }
  else { ... }
 }
};

一个办法是,略微修改一下基类中的Func原型,加上一个无用参数int unused:
 RetType Func(ArgType1 arg1, ArgType2 arg2, int unused = 0);
或者直接改为可变参数:
 RetType Func(ArgType1 arg1, ArgType2 arg2, ...);
当然,派生类重载Func原型还是需要按我们预期的:
 RetType Func(ArgType1 arg1, ArgType2 arg2);

如此,判断“派生类是否重载了Func”就变成了判断函数原型是否为
 RetType Func(ArgType1 arg1, ArgType2 arg2);
而这正是编译器的拿手好戏。

最后提醒一下,阅读WINX源代码时,你可以发现这个技巧有不少变种(消息分派的实现就与此有细节上的不同),但是其中的道理是完全一致的。
在MFC中创建动态控件的生成与响应:【上一篇】
Red Hat 9 Linux下编译sqlite-3.3.8并在QT3.1下连接全过程详细记录:【下一篇】
【相关文章】
  • WINX的消息分派机制(终结篇)
  • WINX的消息分派机制
  • WINX的消息分派机制(续)
  • winxp下配置 Apache2+tomcat5
  • WINX-1.1.01 Released
  • 对比WINX,WTL,MFC,SmartWin代码效率
  • WINX支持DirectX,OpenCV吗?
  • WINX中使用OpenCV的一个样例
  • 局域网内winXP的访问问题
  • winxp下IIS上面的asp.net程序发布
  • 【随机文章】
  • 利用PB实现动态系统用户登录
  • 基于C的CAN总线切换方案
  • 虚拟社区开发项目日志_9
  • 贪吃蛇 J2ME 游戏(0.3+DEMO版)
  • Office 2007的VBA,以及Office开发的随想
  • 深圳市ip 城域网组网方案(19)
  • SQL 存储过程&算法
  • 分页缓存机制(单用户)(C#)
  • 用Fireworks给黑白图上色
  • 学习Java6(一) WebServices (6)传递List(变通方法实现)
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.