注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

为着理想勇敢前进

 
 
 

日志

 
 

悟-透明  

2006-12-09 00:11:43|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

透明就是让你不必知道它干了什么,但你又能轻易的推测出它干了什么,而且它确实“只”做了你推测它会干的事情。

但是有些糟糕的设计却恰恰相反,你不得不弄明白它干了什么,但是你会发现你总是弄不明白它干了什么。有的时候你以为你明白了它干了什么,但是偏偏它不是像你以为的那样干的。这不是绕口令,这个糟糕的设计就是MFC

 

昨天一个同事问我怎么在MFC中关闭MDI中的其中一个子窗口和他的文件。我想都没想就说了句丢个WM_CLOSE给他就行了。但是回过头了有点后怕,因为我根本不知道在MDI中丢一个WM_CLOSE会导致它干什么(而且文档似乎也没说,至少没在显眼的地方说),所以我只好去看源码。

最终还是搞清楚了它是怎么干的,在那个ChildFrame处理WM_CLOSE的OnClose里面,它先检查这个CDocument能否关闭,如果不能就什么事也没有发生的return,然后检查自己是不是整个程序的主窗口,如果是的话,结束程序,然后检查自己是不是最后一个该CDocument的窗口,如果不是就直接关掉,如果已经是最后一个最终则调用当前的文档类的SaveModified(就是弹出来问你到底存不存YesNoCancel那个),默认的CDocument::SaveModified里面可能会触发CDocument::OnSaveDocument的虚函数,然后从SaveModified出来,又触发虚函数OnCloseDocument。CDocument::OnCloseDocument里面又检查什么AutoDelete,看看是不是删除自己,最后再把反过来调用ChildFrame的DestroyWindow。顺便说一句,这个WM_CLOSE除了我们手动产生,另外一个产生途径就是WM_SYSCOMMAND里面的SC_CLOSE,而对SC_CLOSE的默认处理(在Win32 API的DefWindowProc中处理)就是WM_CLOSE

除此之外,MFC中的MDI还有另一个关闭的路径,就是发一个id为ID_FILE_CLOSE的WM_COMMAND消息。说起这个WM_COMMAND的传递路径,更是惊心动魄,发生了一系列你想都想不到的事情。我们知道WM_COMMAND也是属于一个窗口的消息嘛,WM_COMMAND在Win32 API的情况下应该只是那一个窗口处理,但是MFC就相当猛,CMDIFrameWnd里面接受到一个COMMAND它会传递给自己的ActiveChild,就是前台的ChildFrame,然后ChildFrame再传给它对应的ActiveView,这个CView再传给它的CDocument,导致的结果就是一个在主窗口的菜单的命令,可以在从CDocument、CView、CChildFrame和CMDIFrameWnd它本身这里面任何一个类里面用ON_COMMAND来处理。最后CDocument里面处理ID_FILE_CLOSE的默认处理函数OnFileClose又来我们上面提到的SaveModified和OnSaveDocument。(甚至在CWinApp里面也可以ON_COMMAND处理到,这是CFrameWnd干的,它是CMDIFrameWnd和CChildFrame的基类,不过我已经没有耐心去考察为什么它们不会把消息传两次给CWinApp了)

这里存在很多问题,最主要的一个在于这些函数都干了不止一件事情,这个词现在流行叫“正交性”

 

------------------------------------------
2006-12-23 补充:
隐藏实现的含义并不是把实现藏到客户看不见的地方,而是让客户查看接口的时候只用看到接口就能完成任务,没有去看实现的欲望。隐藏实现的接口并不是靠private啥的访问控制强制做到的,而是靠良好的接口定义做到的。
MFC和Win32 API有很多函数的文档出奇的长:
这个函数会干XXX,而且如果你这样做,那么它除了干XXX还会干XXX,如果你想要让他干XXX,那么它会返回一个XXX。还有,如果你不想要它干XXX的话,你一定要传一个XXX过去,否则他就会发生未定义的行为,有的情况下,你可以让他干XXX,但是有的情况下它会帮你干XXX,当然有的情况下它也不会干XXX。最后,你一定不能让他干XXX,那样的话,他虽然会干XXX,但是会导致一个潜在的XXX的问题。

碰到这样的接口定义,如果你不得不用这个API的话,而又想心里有底的话,即使他把这个实现藏到一个二进制的DLL,你也一定会有一种冲动会去跟踪他的反汇编码吧?呵呵,往往那些微软最有价值专家就是这么干的,他们满头大汗的调试过了这些隐藏得很好的实现,就可以故作轻松的告诉小弟们,之所以干XXX不能XXX,那是因为这个微软很牛,它内部使用了一个很牛的技术XXX,因此如果用XXX就会XXX,所以不能XXX。

  评论这张
 
阅读(229)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018