MFC 原理学习笔记

来源:互联网 发布:mac 一键关闭所有窗口 编辑:程序博客网 时间:2024/06/05 05:37

MFC原理学习笔记

 

1.首先,我们根据以上的四个程序可知,主函数的作用是注册,创建和显示窗口,实现消息循环。

 

  由此我们可以将程序中抽象出两个类:窗口类(CFrameWnd),这是很自然的事,由窗口类来完成窗口操作的一系列工作。同时我们将主函数的内容封装为一个类,应用程序类(CWinApp)

 

  1)窗口类中有主函数中窗体创建可知应该有窗口类定义,窗口类注册,窗口创建和现实。同时应该有一个HWND类型的窗口句柄hWnd。对于窗口的显示和更新可以直接调用系统的窗口显示与更新函数。注意由于这两个函数是系统的函数,属于全局函数,需要加全局标识符(::)

 

  2)应用程序类: 把主函数整个函数体做为对象,一个对象对应有其类,可以成为应用程序类,如CWinApp类。其中除了要有m_pMainWnd窗口对象指针作为类的数据成员外,还需要有InitInstance()Run()函数成员函数,InitInstance函数调用窗口对象完成窗口的生成和显示,Run()完成消息循环工作。

 

2.派生与多态:

为了实现程序的个性化,可以利用C++类的继承和多态实现,在现有类基础上派生自己的类,可以在派生类添加自己的数据成员和函数成员,可以将CWinAppInitInstance声明为虚函数,可以在派生类中重写InitInstance函数,进行一些个性化的设置。

应用程序对象指针:

 为了在主函数中使用应用程序类对象,程序员必须在主函数前定义应用程序类对象theAppMFC希望主函数自动生成主函数,自动生成主函数标识符是不可能变化的。

为了解决此问题,在CWinApp中增加了CWinApp*的数据成员m_pCurrentApp在构造函数中把指向对象的this指针赋给它。这样程序员定义了一个应用程序对象后,m_pCurrentApp指向这个对象,为获得该对象,设计一个全局函数AfxGetApp();

CWinApp *AfxGetApp()

{

        return MyApp.m_pCurrentApp;

}

 

3.消息函数的封装——消息映射

      SDK是通过switch-case来映射消息,而MFC希望每一个case的消息处理作为一个消息处理函数,封装到各个类中。

比较简单的一种解决方式:在窗口类中声明一个成员函数AfxWndProc()把窗口的WndProc代码放到AfxWndProc中,最后全局函数WndProc()中调用AfxWndProc()。消息的调用过程图如下:

 

 

 

 

 

 

这样存在的问题只有封装了窗口函数的窗口类或他的派生类才具有或者继承了消息的处理能力。而在Window程序中,不单单是窗口需要处理消息,按钮,滚动条等也需要处理消息,这时的设计是与人们的愿望不一致。最好将窗口函数封装为单独类,希望有消息处理的类可以由它派生,这样可以具有消息处理功能。

 

注:WndProc()函数不能封装到CCmdTarget类中,因为它与WinMain()函数一样是系统哦你调用的回调函数,应该为全局函数。

 

4. MFC的消息映射的组织:

      如同上述的原理,MFC对于每一个类也是使用了一个消息映射表,如同MsgMap工程下的类型,对于每一个类都对用了一个消息映射表,整个系统还维护了一个总的消息映射表(简称为总表)。对于每一个类的消息映射表应该可以添加到总表中,这样才可进行整个系统的消息映射。

      每一个类对应的消息映射表是一个数组,而总表则是使用链表。总表是一个链表,对应每一个类都有一个节点,该节点用于每一类将自己的消息映射表添加到总表中,每一个节点有两个值,pBasemap指向基类的节点,lpEntries指向自己的消息映射表。在每一次应用程序接收到消息后,首先查找自己的消息映射表,如果找到了对应的表项,则直接进行响应;如果自己没有对应的相应函数,则通过pBasemap指针查找自己父类的消息映射表,如此依次向上寻找;如果最终也没有找到对应的表项,则将该消息交给默认的消息过程。

总表与分表的关系如图:

 

 

 

5.直接使用MFC进行编程(不需要系统为我们创建所有东西)

      头文件:

      #include <afxwin.h>

      

      代码:

      需要派生自己的窗口类,填写消息映射表,重载CWinAppInitInstance方法。详细代码见useMFC

注:代码位于我的资源中,分为两个,要全部下载才可以解压成功!

原创粉丝点击