一、需要掌握的技能:
-
断点调试
-
使用 call statck 查看函数的调用关系
-
熟练使用向导和工具
-
借助于 MSDN
二、MFC 的概念和作用
-
什么是MFC?
全称是 Microsoft Foundation Class Library ,我们称微软基础类库。
它封装了 Windows应用程序的各种 API 以及相关机制的 C++类库
-
总结
1 MFC 是一个大的类库
2 MFC 是一个应用程序框架
-
为什么需要MFC?
基于应用程序框架上,使用提供的类库快速开发,提高项目的开发效率,减少开发周期和成本。
三、常见的头文件
-
MFC类库常用的头文件
afx.h -- 将各种 MFC 头文件包含在内
afxwin.h -- 包含了各种MFC窗口类。包含了 afx.h 和 windows.h。
afxext.h -- 提供了扩展窗口类的支持,例如工具栏,状态栏等。
……
四、MFC 程序的分类
01、MFC 控制台程序
-
和 win32 的控制台程序差别
main 函数不同于普通的控制台程序
CWinApp theApp;多了一个全局对象
-
经验之谈:
以 Afx 开头可以确定为 MFC 库中的全局函数。
以 :: 开头可以确定为 win32 的 API 函数
02、MFC 的库程序
-
使用 MFC 制作自己的静态库程序
-
MFC 的动态库
使用静态的 MFC 库制作自己的动态库
使用动态的 MFC 库制作自己的动态库
-
MFC 扩展库
规章库可以被各种程序所调用,扩展库只能被 MFC 程序调用
03、MFC 的窗口程序
相关函数
-
单文档视图架构程序
CWinApp -- 应用程序类,负责管理应用程序的流程
CFrameWnd -- 框架窗口类,负责管理框架窗口
CView -- 视图窗口类,负责显示数据
CDocument -- 文档类,负责管理数据
-
多文档视图架构程序
CWinApp -- 应用程序类
CMDIFrameWnd -- 多文档主框架窗口类
CMDIChildWnd -- 多文档子框架窗口类
CView -- 视图窗口类,显示数据
CDocument -- 文档类,管理数据
-
对话框应用程序
CWinApp -- 应用程序类
CDialog -- 对话框窗口类
五、MFC 库中相关类简介
-
CObject 类
MFC 类库中绝大部分类的父类,提供了 MFC 类库中一些基本的机制。
对运行时类信息的支持
对动态创建的支持
对序列化的支持
-
CWinApp类
应用程序类,封装了应用程序、线程等信息。
-
CDocument类
文档类,管理数据
-
Frame Windows
框架窗口类,封装了窗口程序组成的各种框架窗口
-
CSplitterWnd
用来完成拆分窗口的类
-
Control Bars
控件条类
-
Dialog Boxs
对话框类,封装了各种对话框,通用的对话框
-
Views
视图类,封装了各种显示窗口
-
Control
控件类,封装了各种常用的控件
-
Exceptions
异常处理类,封装了 MFC 中常用的各种异常
-
File
文件类,各种文件的 I/O 操作等
-
绘图类
包括 CDC类 和 CGdiObject类
-
数据集合类
CArray / Clist / CMap,封装了相应的数据结构的管理
-
非CObject类的子类
提供了各种数据结果相关的管理,CPoint,CTime, CString
六、第一个 MFC 程序
01、设置开发环境
-
头文件为 <afxwin.h>
-
setting 当中设置使用 MFC 库
总结:win32 程序和 MFC程序区别仅仅为能不能使用MFC而已。
02、代码书写
-
定义自己的框架类 CMFrameWnd ,派生自 CFrameWnd 类
class CMyFrameWnd :public CFrameWnd{ };
-
定义自己应用程序类 CMyWinApp,派生自 CWinApp 类,并定义 构造 以及 重写 InitInstance 虚函数,在函数中创建并显示窗口。
class CMyWinApp :public CWinApp{ public: CMyWinApp(){ } virtual BOOL InitInstance(){ CMyFrameWnd *pFrame = new CMyFrameWnd; pFrame->Create(NULL, "MFCBase"); m_pMainWnd = pFrame; pFrame->ShowWindow(SW_SHOW); pFrame->UpdateWindow(); return TRUE; } };
-
定义 CMyWinApp 类的对象(程序的爆破点)
CMyWinApp theApp; // 爆破点
七、MFC 程序启动
01、入口函数
-
与 win32 窗口程序相同,都是从 WinMain 入口。但是 MFC 库已经实现了 WinMain 函数,所以在程序中不需要实现。
-
总结:在 win32 中 WinMain 由程序员自己实现,那么流程是程序员安排,但到了 MFC 中,由于 MFC 库实现 WinMain ,也就意味着 MFC 负责安排程序的流程。
02、执行流程
-
程序的启动,构造 theApp 对象,调用 CWinApp 的构造函数
将 theApp 对象的地址保存到线程状态信息中
将 theApp 对象的地址保存到模块状态信息中
进入 WinMain 函数,调用 AfxWinMain 函数
-
进入入口函数 WinMain
获取应用程序类对象 theApp 的地址
利用 theApp 地址调用 InitApplication ,初始化当前应用程序的数据
利用 theApp 地址调用 InitInstance 函数初始化程序,在函数中我们创建窗口并显示
利用 theApp 地址调用 CWinApp 的 Run 函数进行消息循环
如果没有消息,利用 theApp 地址调用 OnIdle 虚函数实现空闲处理
程序退出利用 theApp 地址调用 ExitInstance 虚函数实现退出前的善后处理工作
03、CWinApp 的成员
-
成员虚函数
InitInstance -- 程序的初始化函数,完成了窗口创建等初始化处理
ExitInstance -- 程序退出时调用,清理资源等善后工作
Run -- 消息循环
OnIdle -- 空闲处理函数
-
成员变量
m_pMainWnd -- 当前应用程序的主窗口
八、钩子函数
01、MFC 窗口如何创建
-
创建钩子
HHOOK SetWindowsHookEx( int idHook, // 钩子类型(WH_CBT) HOOKPROC lpfn, // 钩子处理函数 HINSTANCE hMod, // 应用程序实例句柄 DWORD dwThreadId // 线程ID );
-
钩子处理函数
LRESULT CALLBACK CBTProc( int nCode, // 钩子码(HCBT_CREATEWND) WPARAM wParam, // 刚刚创建成功窗口句柄 LPARAM lParam // ... );
-
更改窗口处理函数
LONG_PTR SetWindowLongPtr( HWND hWnd, // 窗口句柄 int nIndex, // GWLP_WNDPROC LONG_PTR dwNewLong // 新的窗口处理函数名(函数地址) );
02、代码书写
-
定义自己的框架类(CMyFrameWnd),派生自 CFrameWnd
-
定义自己的应用程序类(CMyWinApp),派生自 CWinApp,并重写父类成员虚函数 InitInstance
-
定义全局对象 CMyWinApp theApp;(爆破点)
#include <afxwin.h>
class CMyFrameWnd :public CFrameWnd {
};
class CMyWinApp :public CWinApp {
public:
virtual BOOL InitInstance();
};
CMyWinApp theApp; //爆破点
BOOL CMyWinApp:: InitInstance(){
CMyFrameWnd* pFrame = new CMyFrameWnd;
pFrame->Create(NULL, "MFCCreate");
m_pMainWnd = pFrame;
pFrame->ShowWindow(SW_SHOW);
pFrame->UpdateWindow();
return TRUE;
}
03、MFC 窗口创建过程
-
加载菜单
-
调用 CWnd::CreateEx 函数创建窗口
调用 PreCreateWindow 函数设计和注册窗口类调用 AfxDeferRegisterClass 函数,在这个函数中设计窗口类:
WNDCLASS wndcls; //设计窗口类 ... // 定义窗口的处理函数为DefWindowProc wndcls.lpfnWndProc = DefWindowProc;
调用 _AfxRegisterWithIcon 函数
在函数内部,加载图标,并调用 AfxRegisterClass 函数,在函数内部,调用 ::RegisterClass win32 API 函数注册窗口类