`
oscar999
  • 浏览: 216882 次
  • 来自: ...
文章分类
社区版块
存档分类
最新评论

系统理解Win32 API和MFC

 
阅读更多
Win32 API是微软的操作系统Windows提供给开发人员的编程接口,它决定了我们开发的Windows应用程序的能力。MFC是微软为开发人员提供的类库,在某种意义上是对Win32 API的封装。本文试图从全局角度对Win32 API和MFC进行理解──给出二者的概念模型。
本文使用UML描述概念模型。Win32 API本不是面向对象的,我用面向对象的观点去理解它,无非是想表达其全局。
本文参考了MSDN、相关书籍和网上的一些资料,在此一并感谢。

一、Win32 API的概念模型

Win32 API的object有3种:user obj,gdi obj,kernel obj。但是,如果一点不考虑OS本身的支持,就会在有些问题上疑惑,因此,我这里把“operation system负责将中断封装成message”加上。

1、user obj、gdi obj、kernel obj、system 4者的关系

由于是kernel obj部分负责将另外3者联系起来,因此我们在下图中直接深入到kernel obj部分内部。

从图中看到,在内存中运行的,除了“负责将中断封装成message”的system支持部分,还有另外3类object:kernel obj、user obj和gdi obj,每个obj都有一个句柄handle与之对应。其中,gdi obj建立了待开发的Windows 应用和外部输出设备的联系,kernel obj中的file建立了内存和永久存储设备的联系。具体说,内存中的file从可以从硬盘上来,如果这个file是可执行文件,它将生成module, module运行起来就是process,process可以包含多条thread,而thread的运行映象最终还是来自于file。thread是 kernel obj中最重要的一个,因为消息队列就是thread拥有的,只有thread才能够接受message。对gdi obj、urser obj和file的操作,也是发生在thread中的。所以书都讲,process至少拥有一个thread。

2、展开“system负责将中断封装成message”部分

下面展开“system负责将中断封装成message”部分,尽早解除对“message到底是怎么形成的”的困惑。


3、展开“gdi obj”部分

开发人员可以通过gdi obj将app的信息反馈给User。

从图中看到,gdi obj有8种,其中7种为:bmp,brush,pen,region,font,palette,path。另一种比较特殊的是DC,它可以被理解为一 种容器,程序员通过调用SelectPallette()将pallte放入容器,通过调用BeginPath()和EndPath()将path放入容 器,其它5种gdi obj,是通过调用SelectObject()放入容器的。DC又具体分为4种,其中DisplayDC就是最常用的用来支持我们“画Window”的 DC。 另外,如果觉得不好理解,请参考composite设计模式。

4、展开user obj部分

4.1 第1次迭代

window在Windows应用开发中占有重要地位。

从图中看到,window可分为3种:desktop,top-level window,child window。所有window被OS组织成tree,有专门的数据结构来管理。desktop就是树根,desktop的子节点是top-level window,top-level window的子节点是child window,child window仍然可以有子节点,同样归属于child window。tree数据结构中还记录了4种重要信息,是4种指针:parent指针、child指针、brother指针、owner指针。这样,从 任何一个window就能很容易地找到其它window了。

好了,暂且得到 window = desktop + topLevel + child 的结论,看看全局先。毕竟,一步到位有时候并不好。
从图中看到,window确实占有重要地位。从逻辑是讲,thread是window的拥有者;但是,所有window一起决定了屏幕看起来是上面样子, 何况点击任何一个window都会使window得相互覆盖关系发生变化,对所用window进行统一管理是必须的,所以OS又不得不统一用window tree来管理window,反映复杂的window关系。每个window都必须有一个且只能有一个客户区,还可能有一个title bar。 再来看看CreateWindow()函数的interface spec透露了哪些信息。
从图中看到,CreateWindow()负责为window建立与窗口类的联系。每个window都有一个窗口类与之对应,而一个窗口类可以对应多个 window。窗口类中记录了窗口函数和菜单等资源信息,而由file生成的module正是窗口函数和资源的老家。 4.2 第2次迭代

考察消息种类。

从图中看到,每个message都是发送给某个window的。注意,msg可由SYS代码产生,也可以由API函数产生。

进一步考察window,深入topLevel和child。


从图中看到,OVERLAPPED风格的window是top-level window的一种,而另一种POPUP风格的window从本质上(行为上)是特殊的一种OVERLAPPED风格的window,虽然我们从 coding的角度常常不这么认为。

还是不好,因为当我们调用CreateWindow() API函数时,明明感觉CHILD、OVERLAPPED、POPUP是“window style”。我再画一张图。

从图中看到,control必须是CHILD风格的,dialog必须是POPUP风格的,而一般性的window却可以是任意风格的。

4.3 第3次迭代

总结user obj:


CreateDialog()函数示意:

从图中看到,CreateDialog()和CreateWindow()最大的区别就是,它有对话框模板支持方便地定制dialog界面。注意,Dialog是特殊的window,窗口类它一定也是有的。


二、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 回忆API中Message响应函数的安装

API中Message响应函数的安装,是由CreateWindow()实现的,它将window与一个windowClass联系起来,而后者中记录了Message响应函数的指针。
至于细节,看一下如何用Win32 SDK或Win16 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 MFC中Message响应函数的安装

MFC中Message响应函数的安装显然更复杂,是在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,如果处理了要返回true;CWnd::DefWindowProc()负责对message缺省处理。
执行过程是,首先CWnd::CreateEx()被调用,window obj和window class被相应建立,此时window class的WindowProc字段存储了预定义的缺省处理函数的地址;由于有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); 另外,OnWndMsg和DefWindowProc都是CWnd类的虚拟函数。

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


3. SubClass机制


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

4.frame work中的主要相关类

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

5. frame work中的chain of responsability模式

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


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

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

三、 总结
从上面的讨论不难发现,MFC中用到了不少设计模式,如上面提到的chain of responsability模式、composite模式和“订阅-发布”模式。上面的讨论不仅有助于程序员全面掌握Win32 API和MFC,对architect<iframe frameborder="0" marginwidth="">&amp;amp;amp;amp;amp;amp;lt;IFrame frameborder=0 marginwidth=0 marginheight=0 scrolling=no align=center src='http://www.blogbao.com/script.aspx?userid=45735&amp;amp;amp;amp;amp;amp;amp;AdType=0&amp;amp;amp;amp;amp;amp;amp;AdstyleID=46090&amp;amp;amp;amp;amp;amp;amp;Direction=1' width=490 height=150 style='width:490;height:150'/&amp;amp;amp;amp;amp;amp;gt;设计architecture也有很大帮助。&amp;amp;lt;iframe width=&amp;amp;quot;490&amp;amp;quot; scrolling=&amp;amp;quot;no&amp;amp;quot; height=&amp;amp;quot;150&amp;amp;quot; frameborder=&amp;amp;quot;0&amp;amp;quot; align=&amp;amp;quot;middle&amp;amp;quot; marginwidth=&amp;amp;quot;0&amp;amp;quot; marginheight=&amp;amp;quot;0&amp;amp;quot; src=&amp;amp;quot;http://www.blogbao.com/script.aspx?userid=45735&amp;amp;amp;amp;AdType=0&amp;amp;amp;amp;AdstyleID=46090&amp;amp;amp;amp;Direction=1&amp;amp;quot; _fcksavedurl="&amp;amp;quot;http://www.blogbao.com/script.aspx?userid=45735&amp;amp;amp;amp;AdType=0&amp;amp;amp;amp;AdstyleID=46090&amp;amp;amp;amp;Direction=1&amp;amp;quot;" _fcksavedurl=&amp;quot;&amp;amp;quot;http://www.blogbao.com/script.aspx?userid=45735&amp;amp;amp;amp;AdType=0&amp;amp;amp;amp;AdstyleID=46090&amp;amp;amp;amp;Direction=1&amp;amp;quot;&amp;quot; style=&amp;amp;quot;width: 490px; height: 150px;&amp;amp;quot;&amp;amp;gt;</iframe>

<iframe width="490" scrolling="no" height="150" frameborder="0" align="middle" style="width: 490px; height: 150px;" src="http://www.blogbao.com/script.aspx?userid=45735&amp;AdType=0&amp;AdstyleID=49847&amp;Direction=1" marginheight="0" marginwidth="0"> </iframe>
分享到:
评论

相关推荐

    系统理解Win32 API和MFC(下)

    系统理解Win32 API和MFC

    系统理解Win32 API和MFC.pdf

    ### Win32 API与MFC综合理解 #### 一、Win32 API 概念模型解析 ##### **1. Win32 API的核心组件** ...通过本文对Win32 API和MFC的深入理解,开发者可以更好地掌握这两种重要的开发技术,并在实际项目中灵活运用它们。

    系统理解Win32 API和MFC(上)

    系统理解Win32 API和MFC

    mfc类库详解 Win32API大全(全中文版)

    尽管MFC是对Win32 API的封装,但直接使用Win32 API有时能获得更高的灵活性和性能。例如,对于低级窗口操作、内存管理、线程同步等任务,直接使用Win32 API可能更为合适。 学习MFC与Win32 API的结合使用,可以让你:...

    win32程序调用MFC对话框资源

    Win32 API提供了底层的窗口、消息处理和系统服务,而MFC则是在此基础上构建的一套面向对象的库,它封装了Win32 API,简化了Windows应用程序的开发。本文将深入探讨如何在纯Win32程序中调用MFC对话框资源,以及在调用...

    利用win32API模拟MFC的消息映射

    本篇文章将深入探讨如何利用Win32 API来模拟MFC的消息映射,帮助初学者更好地理解和应用这一概念。 首先,我们了解下MFC的消息映射。在MFC中,每个C++类可以关联到一个或多个窗口,这些窗口接收到的Windows消息会被...

    Win32API 和MFC类库详解

    总结来说,深入理解和掌握Win32 API与MFC类库,是Windows平台下进行高效、稳定、专业开发的必备技能。这两份.chm文档,作为详尽的参考资料,将帮助开发者从基础知识到高级技巧全面掌握这两个关键的开发工具。通过...

    C&C++,Win32 API,MFC参考手册

    Win32 API是Windows操作系统提供的底层接口,包含了大量的函数和结构体,用于控制窗口、进程、线程、内存、文件系统等核心功能。Win32 API大全部分将详细阐述如何利用这些API创建和管理Windows应用程序,包括窗口...

    MFC win32 api中文助手

    **MFC Win32 API中文助手**是一款专为C++开发者设计的辅助工具,它集成了C/C++标准库、MFC(Microsoft Foundation Classes)框架和Win32 API的中文文档,极大地方便了中文环境下的编程工作。MFC是微软为Windows平台...

    Win32API是一个vc++初学者必须学习的一门课程,而且API是MFC的重要基础.rar

    对于VC++初学者来说,理解和掌握Win32 API至关重要,因为它是深入理解Windows程序设计的基础,同时,API也是Microsoft Foundation Classes (MFC)库的基础。 首先,让我们探讨一下Win32 API的基本概念。API是一组...

    Win32 API帮助文档以及MFC 中文类库详解

    通过Win32 API,程序员可以创建原生的Windows应用程序,拥有极高的性能和对系统的直接控制权。 MFC(Microsoft Foundation Classes)是微软推出的一个C++类库,它封装了Win32 API,使得开发者能够以面向对象的方式...

    C、C++标准库+mfc类库+Win32API大全

    Win32 API则是Windows操作系统提供的低级接口,用于直接控制系统的硬件和系统服务。 C++标准库,又称为C++ Standard Template Library (STL),包括容器、算法和迭代器等核心组件。容器如vector、list、map和set等,...

    vc及 windows api系列之7

    **VC及Windows API系列之7:系统理解Win32 API和MFC** Windows API(Application Programming Interface)是微软为开发者提供的编程接口,用于构建在Windows操作系统上的应用程序。它提供了丰富的函数、结构和常量...

    新编win32 api大全

    掌握Win32 API,意味着能够深入理解Windows系统的工作原理,编写出性能优秀且具有高度可定制性的程序。 书中详细讲解了Win32 API的基本概念,包括消息机制、窗口类和窗口创建、线程和进程管理、内存分配与管理、...

    文本框(win32不用MFC)

    在Windows编程领域,Win32 API是开发原生Windows应用程序的核心...这样的项目对于理解Win32 API中的文本输入和处理机制非常有帮助,同时也可以作为一个基础,扩展到更复杂的编辑控件功能,如文本格式化、剪贴板操作等。

    win32API手册+MFC类库+Windows程序设计

    综上所述,《win32API手册+MFC类库+Windows程序设计》的学习涵盖了从底层操作系统接口到高级开发工具的全方位知识,对于想要深入理解和开发Windows应用程序的程序员来说,是一份极其宝贵的资源。通过学习和实践,...

    标准Windows程序设计_Visual C++与MFC及Win32API的应用.rar

    《标准Windows程序设计:Visual C++与MFC及Win32API的应用》是关于Windows平台下软件开发的一份宝贵资源,主要聚焦于使用Microsoft Visual C++编程环境,结合MFC(Microsoft Foundation Classes)库和Win32 API进行...

    新编WIN32API大全.zip_MFC_win32 开发

    总之,《新编WIN32API大全》对于从事Win32和MFC开发的程序员来说,是一份宝贵的参考资料,可以帮助他们在开发过程中快速查找所需API,理解其工作原理,并将这些知识应用于实际项目,构建高效稳定且功能丰富的Windows...

    WIN32API For c++.rar

    WIN32API,全称Windows API...虽然现代的开发往往倾向于使用高级框架和库,如.NET Framework、Qt或MFC,但掌握WIN32API能帮助开发者更好地理解底层机制,解决特定问题,尤其在编写轻量级或高性能的应用时。

    c函数、win32api函数、mfc类库查询

    在编程领域,C函数、Win32 API函数和MFC类库是三个至关重要的概念,它们构成了Windows平台下软件开发的基础。这篇详细的知识点解析将深入探讨这些主题,以帮助开发者更好地理解和应用。 首先,C函数是C语言的核心,...

Global site tag (gtag.js) - Google Analytics