系统理解Win32 API和MFC(下)转载

系统理解Win32 APIMFC()
作者: 温昱
作者主页:
lcspace.diy.163.com

系统理解Win32 APIMFC()

二、MFC的概念模型

前面我们研究了WIN32 API"领域模型",对它有较全面的认识。下面,对MFC概念模型的研究,我们把重点放在对app framework的研究上。
app framework
中的message响应/传递机制是最重要的。而Hook机制和Message响应/传递机制是密切相关的,后者以前者为基础。

1. Hook
机制

也许有些程序员只知道hook机制可以编写很""的应用,孰不知MFC本身也是依靠hook机制的。

从图中看到,每个hook拥有一个指针队列,每个指针指向一个称为的HookProc函数,HookProc将在合适的时机被OS调用执行。hook是分不同种类的,其实正是hook的种类决定了它什么时机被OS调用执行。提示,可以看一下"订阅-发布"设计模式以助理解。

2 MFC
Message响应函数的安装

2.1 回忆APIMessage响应函数的安装

APIMessage响应函数的安装,是由CreateWindow()实现的,它将window与一个windowClass联系起来,而后者中记录了Message响应函数的指针。
至于细节,看一下如何用Win32 SDKWin16 SDK写程序就清楚了,其中 DefWindowProc()API函数,负责提供缺省的消息处理,所以,程序员只需要handle需要特殊处理的消息。

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)

{

WNDCLASS wndclass;

...

wndclass.lpfnWndProc =WndProc;

wndclass.lpszClassName = szWindowClass;

...

RegisterClass(&wndclass);

hWnd = CreateWindow( szWindowClass, ...);

...

}

 

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)

{

switch(message)

{

...

return;

}

return DefWindowProc(hwnd,message,wParam,lParam);

}

2.2 MFCMessage响应函数的安装

MFCMessage响应函数的安装显然更复杂,是在CWnd::CreateEx()被调用时完成的,其中还用到了Hook机制。

我们可以先猜一下MFC是怎么做的。MFC支持massage map,使得对消息的响应份散到多个message handler函数中,而不是API开发是那种集中式的消息处理函数;所以,想必会有专门的代码来负责"检索message map table然后调用message handle"message map是为了支持程序员处理他关心的特殊message的,那么缺省的message处理逻辑在哪里呢?答案是MFC创建window obj时是用的"预定义的窗口类",自然已经有了缺省的message处理函数。

从图中看到,CWnd有成员变量m_pfnSuper、成员变量m_hWnd、成员函数OnWndMsg()和成员函数DefWindowProc()Wnd::OnWndMsg()负责"message map中定义的message handle"能否处理到来的message,如果处理了要返回trueCWnd::DefWindowProc()负责对message缺省处理。
执行过程是,首先CWnd::CreateEx()被调用,window objwindow class被相应建立,此时window classWindowProc字段存储了预定义的缺省处理函数的地址;由于有hook在监听窗口创建消息,所以注册的hookProc()会被调用执行,它将classWindow数据结构的WindowProc字段备份到CWnd::m_pfnSuper,再用SetWindowLong()改写classWindow数据结构的WindowProc字段为::AfxWndProc()的地址。当任何一个message到达时,::AfxWndProc()被调用,至于它的逻辑,聪明的你一定猜到了,先调用Wnd::OnWndMsg(),如果返回值为false,还要调用CWnd::DefWindowProc()CWnd::m_pfnSuper指向的缺省处理逻辑,也会在CWnd::DefWindowProc()中被调用。
提示,上面其实有多态情况发生。比如你可以在搜一下pWnd->WindowProc(nMsg, wParam, lParam); 另外,OnWndMsgDefWindowProc都是CWnd类的虚拟函数。

要是觉得不太好理解,最好在VC++里创建一个project实际跟踪一下,下面是我跟踪时调用栈映象的截图。


3. SubClass
机制


从图中看到,SubClass机制以CWnd自身的m_pfnSuper为基础,和"MFCMessage响应函数的安装"很象。

4.frame work
中的主要相关类

frame work
中的主要相关类 就是 message route的候选人,正是它们的OnCmdMsg()共同完成了message route,形成了chain of responsability模式。

5. frame work中的chain of responsability模式

下图是一个对象树,注意消息会在纵向和横向两个方向传播。


消息在纵向方向上的传递,是在"上溯父类的massge map"MFCmessage map完全是为了代替虚函数而采取的手段,而和message route无关。

消息在横向方向上的传递,才是message route,才是chain of responsability模式,由多个相关类的OnCmdMsg()共同完成。

三、 总结
从上面的讨论不难发现,MFC中用到了不少设计模式,如上面提到的chain of responsability模式、composite模式和"订阅-发布"模式。上面的讨论不仅有助于程序员全面掌握Win32 APIMFC,对architect设计architecture也有很大帮助。

posted @ 2008-11-27 20:53  雨城  阅读(695)  评论(0编辑  收藏  举报