MFC
MFC开发
- VS创建MFC项目
点击MyMFC.rc打开资源视图, 找到Dialogs, 右键插入Dialog可以创建新的Dialog界面, 右键Dialog可以创建与其关联的类, 实现逻辑; Dialog很重要, Win32程序就是通过Dialog实现页面的(同理Qt也如此)
- 结构
- CWinApp: 应用程序
- CFrameWnd: 窗口, 类似于画框
- CChildView: 在CFrameWnd中的子窗口, 类似于画布, 微软建议将内容都放在View中
- 使用MFC实现一个有功能的应用程序
- 一开始显示登录对话框, 创建登录对话框要在CWinApp中的CWinApp::InitInstance()调用父类之前创建
- 可以重写对话框的OnInitDlg方法进行一些初始化
- 关闭释放资源需要使用Dialog::Ok()或者Dialog::Cancle()
- 控件和对应的变量对应数据同步问题
- UpdateData(TRUE)将控件中的数据同步到变量中
- UpdateData(FALSE)将变量中的数据同步到控件中
- 在对话框中如果选择Edit Control(文本输入框)时回车则调用对话框的OnOk方法, 按住esc则调用OnCancle()方法, 如果有需要可以重写这两个方法
- 当点击对话框右上角的叉号时, 会发出WM_CLOSE消息, 可以在对话框中添加该消息处理点击叉号时的逻辑(比如退出应用程序)
- 关闭应用程序直接调用exit(0)函数
- 在MFC中的事件特质菜单等发出的命令(Command), 我们现代框架中的事件是MFC中的消息
- 在MFC诞生的时候, C++也在发展, 但是那个时候C++并没有提供运行时(typeid)等, 但是当时MFC正需要, 所以MFC通过C++实现了(通过定义一些宏), 大致思路如下
- 在一个类中使用DECLARE_DYNAMIC宏, 在.cpp文件中使用IMPLEMENT_DYNAMIC宏
- 原理
- DECLARE_DYNAMIC为类添加了RuntimeClass *, 非常类似于Java中的Class, RuntimeClass类中包括当前类的名称(通过宏参数确定), 当前类的父类(只有一个父类, 所以实现了单继承), 当前的大小(sizeof(class CurrentClass)), 还定义了一个返回值为当前类类型的函数指针Create(目的就是让用户拿到了RuntimeClass也可以创建类的对象, 经典的反射); 除了声明了RuntimeClass类之外, 还定义了静态方法Create(), 因为RuntimeClass中有Create函数指针, 将指针指向该静态方法, 就能实现RuntimeClass.Create()创建对象
- IMPLEMENT_DYNAMIC实现上面定义的所有东西, 静态Create方法中返回new Class;
- 在Win32 API为了处理消息使用到了 switch, 但是很麻烦, MFC对其进行了封装, 也是通过定义宏的方式, 使用DECLARE_MESSAGE_MAP宏, 在.cpp文件中使用BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏包围起来, 里面写ON_xxx宏
- 原理
- DECLARE_MESSAGE_MAP定义了MessageMap变量, 该变量用于保存当前类要处理哪些消息, 就是Win32 API中switch中的case, 还有一个 entry指针, 用于指向父类的MessageMap, 起到了传递窗口的作用, 否则MFC在实现消息的窗口传递的时候消息就断了
- BEGIN_MESSAGE_MAP和END_MESSAGE_MAP合在一起就是一个结构体数组的初始化, END_MESSAGE_MAP中就包含有结构体数组初始化表达式的}括号
- ON_xxx系列宏就是为结构体数据中的结构体初始化表达式, 里面还会指定回调函数(比如OnLButtonDown, 此函数是当前类的静态成员函数, 需要用户自己定义)
- 建议
- 别用MFC了, 人生苦短, 用Qt吧
- MFC可以用来自己实现一个运行时