从Win32过渡到MFC工程
MFC简介
MFC(Microsoft Foundation Classes),是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows的API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。
MFC程序就是基于MFC编译出来的可执行程序,是一种GUI程序。
VS2019下MFC程序建立
新建Windows桌面向导
选择应用程序类型、建立一个空项目
当选择为桌面应用程序后,
项目属性下的C/C++->预处理器->预处理定义下就有_WINDOWS的宏定义。
链接器->子系统下选择项就为:窗口 (/SUBSYSTEM:WINDOWS)。
MFC程序内容书写
这样一个空项目建立好,然后源文件下-->新建CPP文件MyFirstMFC.cpp.
MFC程序分三步:
1、建立CWinApp的派生类
class CMyApp : public CWinApp { public: CMyApp() { } ~CMyApp() { } //看做是入口函数,MFC的所有代码都从这里开始 //InitInstance : MFC的初始化过程,启动管理 //目的:为了初始化应用程序,虚函数 virtual BOOL InitInstance() { //第一个对话框窗口 CMainDlg dlg; INT_PTR res=dlg.DoModal();//弹出一个模态对话框
if(res==IDOK)
{
AfxMessageBox(_T("弹出对话框"));
} return TRUE;//TRUE:表示初始化成功,返回FALSE表示关闭应用程序 } //负责清理操作 int ExitInstance() { return CWinApp::ExitInstance(); } };
CMyApp::CMyApp()
{
}
CMyApp::~CMyApp()
{
}
2、重写InitInstance虚函数
如上面代码所示,子类CMyApp重写了基类CwinApp的InitInstance函数。
InitInstance函数是程序的入口函数,WinMain函数隐藏在这个函数中。在实际的开发中,一般不需要对这个类进行操作,但如果需要在建立主对话框之前处理一些数据或者准备工作,那么就可以把代码添加到这个函数中,主对话框显示之前。
3、定义CWinApp派生的全局对象
CMyApp theApp;
其为MFC应用程序的核心对象,一个应用程序有且只有一个theApp。
MFC程序整个的执行过程大致如下:
1.Windows将用户程序装入内存;
2.构造全程对象theApp,在程序被装入时,所有全程对象(全局变量对象)都会立刻被创建;
3.Windows调用全程函数WinMain,它是类库的一部分;
4.WinMain会自动搜索CWinApp派生类的唯一实例;
5.在找到后,WinMain会调用theApp的InitInstance函数,它在派生类中被重新设置了;
6.被重新设置的InitInstance函数启动了文档的装入以主要框架和视的显示处理过程;
7.然后,WinMain调用theApp的Run函数,它启动窗口消息和命令消息的传递处理过程;
当一个应用程序被中止,所有窗口被关闭后,ExitInstance函数会被自动调用。
关于MFC程序执行流程的解析,请查看《XXXX》文章。
这里提醒一下,关于第二步提到全局变量(对象),我们要明确一点,全局变量的执行是优先于主函数的(main、WinMain)。
控制台程序:
#include <iostream> using namespace std; int a = 30;//全局变量 生命周期:从程序的开始到程序的结束销毁 // mainCRTStartup class Hello { public: Hello() { cout << "这是Hello构造函数" << endl; } }; Hello hello;//全局对象, 首先构造hello对象 int main() { cout << "这是main函数" << endl; int b = 40; cout << a << " " << b << endl;//30 40 return 0; }
可以看到先实例化了全局对象hello,而后执行main函数。
修改VS配置信息
在配置属性->高级->MFC的使用一览选择:在共享 DLL 中使用 MFC或在静态库中使用 MFC。
在上面的例子中,我们是希望在主程序执行时,弹出一个模态对话框,对话框的定义信息如下:
#include<afxwin.h> #include"resource.h" class CMainDlg :public CDialog { private: HICON m_hIcon; public: enum { IDD = IDD_MAIN_DLG }; public: CMainDlg() :CDialog(IDD) { } BOOL OnInitDialog() { SetWindowText(_T("weiyin")); m_hIcon=::LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDI_ICON1)); SetIcon(m_hIcon, true); return true; } };
MFC实例句柄的获取
在win32桌面程序中,WinMain函数的第一个形参就是当前程序的实例句柄:hInstance.而MFC中要获取其实例句柄,设置图标的时候,可以采用以下几种方式获取。
//加载图标 hInstance //MFC中如何获取实例句柄: //1 . AfxGetInstanceHandle() //2 . AfxGetApp()->m_hInstance //1.m_hIcon = ::LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDI_ICON1)); m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
Win32 API与MFC API
当MFC API与win32 API同名冲突时,我们一般约定:
:: 如果::的前面是没有类名来修饰,那么,表示调用的是Win32 API函数 。eg ::LoadIcon()
加了前缀类名的为当前类的成员函数。
没有加::的函数为MFC API函数,其一般是以Afx开头的的全局函数,都能在MFC工程中使用。