一、MFC的概念和作用
1.什么是MFC?
全称为Microsoft Fundation Class Library我们称之为微软基础类库
(1)从硬盘的存在形式来说MFC就是一个库(静态库)
(2)从原理上来说MFC还是一个程序框架
2.为什么使用MFC?
基于框架编程提高工作效率,减少开发周期,降低开发成本
二、几个重要头文件
afx.h - 包含了绝大部分MFC库中的类和声明
afxwin.h - 包含了afx.h和windows.h
afxext.h - 包含了关于扩展窗口类声明,例如:工具栏、状态栏等
附:以Afx开头的函数就可以确定是MFC库中封装的全局函数
以::开头的函数就可以确定是win32的API函数(user32.dll/kernel32.dll/gdi32.dll)
三、MFC应用程序类型
1.使用MFC库制作自己的控制台程序
(1)多了全局对象CWinApp theApp
(2)入口函数不同于win32的入口函数
2.使用MFC库制作自己的静态库程序
3.使用MFC库制作自己的动态库程序
(1)使用(静态/动态)MFC库制作自己的规则动态库程序
(2)使用MFC制作自己的扩展库
规则动态库可以被任何程序调用,扩展动态库库只能被支持MFC的程序调用
4.使用MFC库制作自己的窗口程序
(1)单文档视图构架程序
CFrameWnd - 框架窗口类,封装了关于框架窗口的操作
CWinApp - 应用程序类,负责管理程序的流程
CDocument - 文档类,封装了关于数据的操作(提取/转换/存储数据)
CView - 视图窗口类,封装了关于视图窗口的操作(显示数据)
(2)多文档视图构架程序
CMDIChildWnd - 子框架窗口,封装了关于子框架窗口的操作
CMDIFrameWnd - 主框架窗口类,封装了关于主框架窗口的操作
CWinApp - 应用程序类,负责管理程序的流程
CDocument - 文档类,封装了关于数据的操作(提取/转换/存储数据)
CView - 视图窗口类,封装了关于视图窗口的操作(显示数据)
(3)对话框构架程序
CWinApp - 应用程序类,负责管理程序的流程
CDialog - 对话框窗口类,封装了关于对话框窗口的操作
四、MFC库中类概述
1. CObject - MFC库中绝大部分类的基类
运行时类信息机制 / 动态创建机制 / 序列化机制
2. CCmadTarget - 消息映射的最基类
3. CWinThread / CWinApp - 应用程序类
4. CDocument及其子类 - 文档类,负责管理数据
5. Exceptions - 异常处理类,封装了MFC各种异常的处理
6. CFile及其子类 - 文件操作类,封装了关于各种文档的读写等操作
7. CWnd - 所有窗口类的最基类
8. FrameWindows - 框架窗口类,封装了关于各种框架窗口的操作
9. DialogBoxes - 对话窗口类,封装了关于各种对话框串口的操作
10. Views - 视图窗口类,封装了关于各种视图窗口的操作
11. Controls - 控件窗口类,封装了关于各种控件窗口的操作
12. CDC及其子类 - 封装了各种绘图设备,以及绘图函数
13. CGdiObject及其子类 - 封装了关于各种GDI绘图对象的操作
14. CArray / CMap / CList及其子类 - 封装了C++语法中相应的数据结构
15. 非CObject类 - 对各种结构进行了封装
例如:CPoint / CRect / CTime / CString
五、第一个MFC程序
1.配置环境
(1)删除入口函数WinMain
(2)将头文件<windows.h>改为<afxwin.h>
(3)属性->常规中设置为使用MFC库(静态库动态都可以)
2.代码
(1)从CFrameWnd类派生了一个自己的框架窗口类CMyFrameWnd
(2)从CWinApp类派生了一个自己的应用程序类CMyWinApp,并在类中重写了父类的虚函数InitInstance
代码:
#include "stdafx.h" class CMyFrameWnd : public CFrameWnd { }; class CMyWinApp : public CWinApp { public: CMyWinApp(); virtual BOOL InitInstance(); }; CMyWinApp::CMyWinApp() { } CMyWinApp theApp; BOOL CMyWinApp::InitInstance() { CMyFrameWnd *pFrame = new CMyFrameWnd; pFrame->Create(NULL, L"MFCBase"); m_pMainWnd = pFrame; pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE; }
六、程序的执行过程
1.构造theApp
(1)将theApp的地址保存到当前程序线程状态信息中
(2)将theApp的地址保存到当前程序模块状态信息中
(3)AfxGetApp() / AfxGetThread() - 返回theApp的地址
伪代码:
AFX_MODULE_STATE g_ModuleState; //当前程序模块状态信息(MFC中的全局变量,我这里的变量名是随便起的)
AFX_MODULE_THREAD_STATE g_ThreadState; //当前程序线程状态信息
CWinApp::CWinApp( ... ) //构造theApp对象
{
//获取全局变量&g_ModuleState,AfxGetModuleState();
AFX_MODULE_STATE* pMoudleState = _AFX_CMDTARGET_GETSTATE();
//获取全局变量&g_ThreadState,可以看出m_thread是g_MouleState的成员
AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;
//将&theApp保存到pThreadState的成员变量中
pThreadState->m_pCurrentWinThread = this;
CWinThread* AFXAPI AfxGetThread( )
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState( ); //获取全局变量&g_MoudleThreadState
CWinThread* pThread = pState->m_pCurrentWinThread; //从g_MoudleThreadState取出&theApp赋值给pThread
return pThread;
}
pModuleState->m_pCurrentWinApp = this; //将&theApp保存到g_ModuleState的成员中
CWinApp* AfxGetApp( )
{
return afxCurrentWinApp; //宏替换为:AfxGetModleState( )->m_pCurrentWinApp,返回&theApp
}
}
2.进入入口函数(WinMain),开始程序流程
(1)获取theApp对象的地址
(2)利用theApp调用应用程序类成员虚函数InitApplication(初始化)
(3)利用theApp调用应用程序类成员虚函数InitInstance(创建并显示窗口)
(4)利用theApp调用应用程序类成员虚函数Run(消息循环)
如果没有消息,利用theApp调用应用程序类成员虚函数OnIdle(空闲处理)
如果有WM_QUIT消息,利用theApp调用应用程序类成员虚函数ExitInstance(善后处理)
伪代码:
WinMain( ... )
{
AfxWinMain( ... )
{
CWinThread* pThread = AfxGetThread( ); //返回theApp的地址
CWinApp* pApp = AfxGetApp( ); //返回theApp的地址
pApp->InitApplication( ); //利用theApp调用应用程序类成员虚函数(初始化)
pThread->InitInstance( ) //利用theApp调用应用程序类的成员虚函数
{
//回到自己的代码
}
pThread->Run( ) //利用theApp调用应用程序类的成员虚函数(消息循环),函数内部this为theApp的地址
{
CWinThread::Run( ) //函数内部this为theApp的地址
{
while ( 没有消息 )
{
OnIdle( ); //利用theApp调用应用程序类的成员虚函数(空闲处理)
}
do
{
if ( GetMessage捕获WM_QUIT )
return ExitInstance( ); //利用theApp调用应用程序类的成员虚函数(善后处理)
} while ( ... );
}
}
}
}
七、CWinApp成员虚函数
目前为止我们知道的虚函数:
InitApplication / InitInstance / Run / OnIdle / ExitInstance