WINX的消息分派机制(终结篇)

来源:互联网 发布:linux无法删除用户 编辑:程序博客网 时间:2024/04/28 00:53

你已经了解了WINX的消息分派,这里我们总结一下,并交代一些前文为了思路紧凑而略过的一些细节,内容包括:

  • WINX消息分派的总体特色。
  • 与MFC、WTL相比它有什么优点与劣势。
  • Default函数是如何实现的。

开发WINX的时候,尽管我决定尽量重用WTL,以便这个界面库不至于和Sourceforge上其他众多的界面库一样,最后只是一个实验品(它们无法流行的原因多数在于体系封闭而个人精力有限而无法提供与当前流行的界面库同等的功能),只是拥有少量的忠实拥护者,但是最终无法成为工业级的产品(在我看来,C++界面库比较成功的有MFC、QT、wxWidgets,而WTL只能算半个)。但是,消息分派机制上我决定不沿袭WTL,而是自己提供全新的实现。

WTL的消息机制是极其灵活的,通过它你很容易将功能划分为一个个独立而且含义完整的功能切片。但是问题在于,这种灵活给用户带来了困惑:深奥的模板技术、复杂的消息机制、晦涩而丑陋的代码,用户望而却步了。

WINX的消息机制给用户最简洁的界面,并尽量与MFC的消息兼容。另一方面,WINX的消息分派的智能带来了另一个好处:WINX不断可以增加新的消息,只要派生类没用响应它,就没有任何额外开销。进而,我们可以为WINX加入任何新特性,只要用户没用使用该特性,那么就没用额外代价。——这很有趣。你马上可以想到,WTL的一个个功能切片,WINX也可以提供,并且可以以更为简洁的方式提供。

WINX的消息分派是高效的。一部分原因你已经了解到了:WINX它可以智能的了解派生类并做出优化。还有一个细节,同样与性能有关:WINX的消息响应次序在DispatchMessage中已经精心安排好了。你可以想象,把WM_PAINT消息放到switch..case的最后,还是放在最前,这对消息函数的执行效率产生了怎样的影响。而WTL中是由你自己去安排消息响应的次序,这对使用者是一个额外的负担。——这不只是因为性能的因素,WTL中某些功能切片的安放是有次序要求的,交换次序后会有细节上的行为差异。

WINX的消息机制最大的问题在于,由于我们随时可能会为了实现一个作用于所有窗口的新特性而添加新消息,故此,为了方便你未来升级WINX到更高的版本,你派生的窗口类需要小心定义其成员函数名。我的一个建议是,请尽量不要自定义一些以On开头的函数名。如果确实需要,建议引入类似命名空间的法则:例如,所有响应命令的函数统一以OnCmdXXX命名之。

MFC在你响应消息中希望执行默认处理时,除了调用基类的同名方法外,更为常见的方法是调用Default()函数。同样,WINX也提供了该函数,并且实现方式类似,大体代码如下:

__declspec(thread) PackedMessage _g_currMsg;

template 
<class T>
class WindowMessage
{
public:
 LRESULT Default()
 {
  T
* pThis = static_cast<T*>(this);
  
return pThis->InternalDefault(
   _g_currMsg.hWnd, _g_currMsg.message,
   _g_currMsg.wParam, _g_currMsg.lParam);
 }

 LRESULT ProcessMessage(
   HWND hWnd, UINT message ,
   WPARAM wParam, LPARAM lParam)
 {
  LRESULT lResult 
= 0;
  PackedMessage oldMsg 
= _g_currMsg;
  _g_currMsg.hWnd 
= hWnd;
  _g_currMsg.message 
= message;
  _g_currMsg.wParam 
= wParam;
  _g_currMsg.lParam 
= lParam;
  BOOL fProcess 
= DispatchMessage(
    hWnd, message, wParam, lParam, lResult);
  
if (!fProcess)
   lResult 
= Defalut();
  _g_currMsg 
= oldMsg;
  
return lResult;
 }
};

 

原创粉丝点击