03 编写第一个MFC应用程序
微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。要使用MFC功能,必须包含头文件“Afxwin.h”。
MFC有两个非常重要的类:
1、CWinApp(应用程序类)
CWinApp的继承关系:CObject->CCmdTarget->CWinThread->CWinApp
MFC应用程序的核心就是基于CWinApp类的应用程序对象。CWinApp提供了消息循环来检索消息并将消息调度给应用程序窗口。一个MFC程序可以有且仅有一个应用程序对象,此对象必须声明为在全局范围内有效,以便它在程序开始时即在内存中被实例化。
(1)InitInstance函数
当你从CWinApp继承应用程序类的时候,应重载InitInstance成员函数以创建应用程序的主窗口对象。InitInstance的目的是给应用程序提供一个自身初始化的机会,其返回值决定了框架接下来要执行的内容,如果返回FALSE将关闭应用程序,如果初始化正常返回TRUE以便允许程序继续进行。此函数是MFC应用程序的入口。
(2) m_pMainWnd成员变量
在 CWinApp 中有一个名为 m_pMainWnd 的成员变量。 该变量是一个 CWnd 类型的指针,它保存了应用程序框架窗口对象的指针。也就是说,是指向 CFramWnd 对象(框架窗口类对象)的指针。
2、CFrameWnd(窗口框架类)
CFrameWnd的继承关系:CObject->CCmdTarget->CWnd->CFrameWnd
MFC的CWnd类以及其派生类为 窗口 或 应用程序创建的窗口 提供了面向对象的接口。CFrameWnd就是从CWnd派生出来的。CFrameWnd模仿框架窗口行为,我们可以把框架窗口作为顶层窗口看待,它是应用程序与外部世界的主要接口。
如果想要创建一个窗口,可以在此类中调用Create或CreateEX函数,并且在CWinApp::InitInstance中创建一个框架窗口对象,并通过ShowWindow函数将其显示出来。
CFrameWnd::Create原型如下:
BOOL Create(
LPCTSTR lpszClassName,
LPCTSTR lpszWindowName,
DWORD dwStyle = WS_OVERLAPPEDWINDOW,
const RECT &rect = rectDefault,
CWnd* pParentWnd = NULL,
LPCTSTR lpszMenuName = NULL,
DWORD dwExStyle = 0,
CCreateContext* pContext = NULL
);
/*
返回值:如果初始化成功,则返回非零值,否则为0。
参数: lpszClassName 指向一个用于命名Windows类的以空终止的字符串。类名可以是任何以AfxRegisterJWndClass全局函数登记或RegisterClassWindows函数登记的名。如果为NULL,使用预定义的缺省CFrameWnd属性。
lpszWindowName 指向代表窗口名的以空终止的字符串,用作标题条的文本。
dwStyle 指定窗口风格属性。如果想标题条自动显示窗口代表的文档名,则应包含FWS_ADDTOTITLE风格。
rect 定义窗口大小和位置。rectDefault值使Windows为一个新窗口指定大小和位置。
pParentWnd 指定框架窗口的父窗口,对最高层框架窗口来说应为NULL。
lpszMenuName 指定与窗口一起使用的菜单资源名。如果菜单有一个整数ID而不是字符串ID,则使用MAKEINTRESOURCE。此参数可为NULL。
dwExStyle 指定窗口扩展的风格属性。
pContext 指向CCreateContext结构的指针。可为NULL。
说明:
分两步构造一个CFrameWnd对象。首先调用构造函数来构造CFrameWnd对象,然后调用Create来构造Windows框架窗口并把它附加给CFrameWnd对象,Create初始化窗口的类名、窗口名,登记它的风格、父窗口和相关菜单的缺省值。
使用LoadFrame而不用Create来从资源而不是指定其参数加载一个框架窗口。
*/
示例代码如下:
#include <afxwin.h>
//1)应用程序类 CWinApp, 派生类(子类)
class MyApp : public CWinApp
{
public:
//基类的虚函数
//派生类只是重写
//MFC程序的入口地址
virtual BOOL InitInstance();
};
//2)框架类 CFrameWnd, 派生类(子类)
class MyFrame : public CFrameWnd
{
public:
MyFrame();
//声明消息映射宏
DECLARE_MESSAGE_MAP()
afx_msg void OnLButtonDown(UINT, CPoint);
afx_msg void OnPaint();
private:
};
//有且只有一个全局的应用程序类对象
MyApp myApp;
//程序的入口地址
BOOL MyApp::InitInstance()
{
/*
1、创建框架类对象
2、显示窗口
3、更新窗口
4、保存框架类对象指针
*/
//1、创建框架类对象
MyFrame *frame = new MyFrame; //构造函数
// 2、显示窗口
frame->ShowWindow(SW_SHOWNORMAL);
// 3、更新窗口
frame->UpdateWindow();
//4、保存框架类对象指针
m_pMainWnd = frame;
return TRUE;
}
//定义消息宏
BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)
ON_WM_LBUTTONDOWN()
ON_WM_PAINT()
END_MESSAGE_MAP()
MyFrame::MyFrame()
{
//CWnd类的成员函数 CWnd::Create
//CFrameWnd 继承于 CWnd
Create(NULL, TEXT("MFC"));
}
void MyFrame::OnLButtonDown(UINT, CPoint)
{
//CWnd::MessageBox
MessageBox(TEXT("鼠标左键"));
}
void MyFrame::OnPaint()
{
// QPainter p(this);
// p.drawxxxx();
CPaintDC cdc(this);
cdc.TextOutW(100, 100, TEXT("你好,mfc"));
}
点击左键,运行结果如下:
备注:如果代码运行错误,需要到右击项目,选择属性,在常规里面,有个MFC的使用项,选择“在共享DLL中使用MFC”,重新编译运行即可: