mfc中的消息的应用

类别:VC语言 点击:0 评论:0 推荐:

 mfc中的消息莫是相对于虚函数表来说到底有什么优势?有人说是空间上面有好处。既可以省下长长的虚函数表的内存。比如:
 用虚函数的话,window的基类会是
 class window
 {
  virtual OnSize() = 0;
  virtual OnMove() = 0;
  virtual OnContextMenu() = 0;
  ……等等
 }
 可想而知,每个由此继承而来的子类将会负担多么大的虚函数表,光是windows自带的就有数十个之多。当然不可取。
 
 可是除此之外,似乎有一种观点是如果机器够快的话就可以采用虚函数的方法了,哪只不不过是ms在当年的无奈之举。嗬嗬,真的是这样吗?非也!
 其一、如果有自定义的消息怎么办?修改基类?
 其二、其实在窗口间互相传递消息可以看成是互相的请求服务,此服务被请求窗体可以响应,也可以不响应。这种灵活性是虚函数方法所无法取得的——如果不支持的话,嗬嗬,对不起,编译时便会报错了。请求方对于被请求方的所有要求仅仅是其是CCmdTarget的子类即可。怎么样,正所谓便宜实惠量又足啊。可就是不太好理解,所以ms提供了许多宏来做这件事情。 
 
 下面看一个具体的例子。这是一个关于treectrl操作的例子。这是一棵表示公司组织的树,上面的节点有
 公司
    ----人事科
          -----张三
          -----李四 
    ----采购 
            -----王二
            -----麻子
 
 即三类节点,公司、科室、员工
 
 当客户右击鼠标时,对于不同的节点弹出的菜单当然是不同的。 
 做法1、判断三种节点的图标,(假定用不同的图标显示不同节点)然后针对不同的情况弹出菜单。这种方法对于显然不妥,有点像经典的
 if ( obj.typeid == ...)
  do something
 else if ( obj.typeid == .. )
  do somthine else ...
 结果就是在treectrl的代码中充满了这样的判断代码
 
 做法2、有class Company, class office, class person,均从CCmdTarget继承。当insert treeitem的时候,产生对象,将其指针和插入的item联系起来,方法可以采用SetItemData(对象的指针),这样的话,处理弹出菜单的方法就变为
 treectrl::OnContextMenu(...)
 {
  CCmdTarget* p = GetItemData(hSelItem);
  p->sendcommand(wm_contextmenu, point)
 }
 这样就ok了。但是有一个缺点,占用太多的内存了!每个item都有多出sizeof(CCmdTarget),有点过分。
 再改进——做法3
 class Company, office, person不变,
 但增加他们的工厂类
 
 class treeitemor
 {
  virtual CCmdTarget* CreateItem() = 0;
 }
 class Companyor
 {
  long m_ID;
  virtual CmdTarget* CreateItem(); //产生Company类
 }
 class office和person同上
 
 弹出菜单变为
 treectrl::OnContextMenu(...)
 {
  treeItemor* ItemCreator = GetItemData(hSelItem);
  CCmdTarget *pCmd = ItemCreator->CreateItem();
  pCmd->SendCommand(WM_CONTEXTMENU, POINT);
 }
 
 呼!总算完了。最后请大家多提意见!

 

  
 

本文地址:http://com.8s8s.com/it/it2208.htm