一、概念
MFC(MicrosoftFoundationClasses)是微软基础类库的简称,是微软公司实现的一个c++类库,主要封装了大部分的windows API函数,vc++是 微软公司开发的c/c++的集成开发环境,所谓集成开发环境,就是说利用它可以编辑,编译,调试,而不是使用多种工具轮换操作,灵活性较大。vc也指它的内部编译器,集成开发环境必须有一个编译器内核,例如DevC++其中一个编译器内核就是gcc。 MFC除了是一个类库以外,还是一个框架,在vc++里新建一个MFC的工程,开发环境会自动帮你产生许多文件,同时它使用了mfcxx.dll。xx是版本,它封装了mfc内核,所以你在你的代码看不到原本的SDK编程中的消息循环等等东西,因为MFC框架帮你封装好了,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西,但是由于是通用框架,没有最好的针对性,当然也就丧失了一些灵活性和效率。但是MFC的封装很浅,所以效率上损失不大。
二、在MFC下创建一个窗口对象
MFC下创建一个窗口对象分两步,首先创建MFC窗口对象,然后创建对应的Windows窗口。在内存使用上,MFC窗口对象可以在栈或者堆(使用new创建)中创建。具体表述如下:
创建MFC窗口对象。通过定义一个CWnd或其派生类的实例变量或者动态创建一个MFC窗口的实例,前者在栈空间创建一个MFC窗口对象,后者在堆空间创建一个MFC窗口对象。
调用相应的窗口创建函数,创建Windows窗口对象。
例如:在前面提到的AppWizard产生的源码中,有CMainFrame(派生于CMDIFrame(SDI)或者CMDIFrameWnd(MDI))类。它有两个成员变量定义如下:
CToolBar m_wndToolBar;
CStatusBar m_wndStatusBar;
当创建CMainFrame类对象时,上面两个MFC Object也被构造。
CMainFrame还有一个成员函数
OnCreate(LPCREATESTRUCT lpCreateStruct),
它的实现包含如下一段代码,调用CToolBar和CStatusBar的成员函数Create来创建上述两个MFC对象对应的工具栏HWND窗口和状态栏HWND窗口:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
…
if (!m_wndToolBar.Create(this) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}
…
}
关于工具栏、状态栏将在后续有关章节作详细讨论。
在MFC中,还提供了一种动态创建技术。动态创建的过程实际上也如上所述分两步,只不过MFC使用这个技术是由框架自动地完成整个过程的。通常框架窗口、文档框架窗口、视使用了动态创建。介于MFC的结构,CFrameWnd和CView及其派生类的实例即使不使用动态创建,也要用new在堆中分配。理由见窗口的销毁(2.2.5节)。
至于动态创建技术,将在下一章具体讨论。
在Windows窗口的创建过程中,将发送一些消息,如:
在创建了窗口的非客户区(Nonclient area)之后,发送消息WM_NCCREATE;
在创建了窗口的客户区(client area)之后,发送消息WM_CREATE;
窗口的窗口过程在窗口显示之前收到这两个消息。
如果是子窗口,在发送了上述两个消息之后,还给父窗口发送WM_PARENATNOTIFY消息。其他类或风格的窗口可能发送更多的消息,具体参见SDK开发文档。
三、MFC编程的缺点
1.大量使用稀奇古怪的宏,会使代码可读性很差。要掌握MFC需要编程人员耐心的去分析它们。
2.消息映射的现实机制十分笨拙,没有采用继承机制,也没有采用委托技术,而是采用表驱动。
3.对于底层SDK的封装太薄,面向对象的感觉不足。
4.自己编写了RTTI,SHE,CObjXXX(Container)等,实现起来不太理想。
5.很多场合本来是标准库可以一展身手的地方,MFC完全没用上。
6.为了迎合MFC,编译器的很多地方都违反标准。
7.Doc/View体系的局限性,想图破很难。
四、一个MFC编程的例子
1. 由于mfc只是对win32API进行了大量的封装,因此可以通过修改win32项目来创建mfc工程
2. 工程名起名为FirstMFC,然后下一步选择windows应用程序,然后点击完成
3. 创建完成后发现主cpp文件已经为我们自动生成了win32创建窗口的代码,因为要用mfc实现,所以只需保留头文件,删掉其余的代码
FirstMFC.cpp内只剩下如下代码
// FirstMFC.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "FirstMFC.h"
4.由于我们要使用MFC库,因此需要在stdafx头文件里包含afxwin.h 而afxwin.h内已经包含windows.h,因此可以直接将stdafx.h内的#include 替换成。
5. 右键点击工程名,选择属性,在弹出对话框中MFC使用这一项选择在静态库中使用MFC,然后选择应用确定。
6. 因为mfc程序需要至少包含一个应用程序类和窗口框架类,因此我们需要在FirstMFC.cpp定义一个CFrameWnd和CWinApp的子类,并为CWinApp的子类创建一个全局的实
例化对象,并在CwinApp的子类中重载InitInstance函数创建窗口,代码如下:
- class CMyFrameWnd : public CFrameWnd
- {
-
- };
-
- class CMyWinApp : public CWinApp
- {
- virtual BOOL InitInstance();
- };
-
- CMyWinApp myApp;
- InitInstance函数中创建窗口代码如下
"code" class="cpp">BOOL CMyWinApp::InitInstance()
- {
- CMyFrameWnd * pFrame = new CMyFrameWnd();
- pFrame->Create(NULL,"FirstMFC");
- m_pMainWnd = pFrame;
- pFrame->ShowWindow(SW_SHOW);
- pFrame->UpdateWindow();
- return TRUE;
- }
从代码可以看出,InitInstance主要完成的工作就是窗口的创建过程,查阅csdn可以发现
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 );
create函数的第一个参数为类名,可以置空,在创建的过程中mfc会自己重新为它赋值,第二个参数为要创建的窗口的名称,后面的参数固定参数,无须赋值