Ⅰ 基于对话框的MFC应用程序怎么建立
使用VC6.0构建最简单的MFC程序
通过这个例子可以加深对MFC的CWinApp和CFrameWnd的了解。
1. 使用应用程序向导产生一个空的“Win32 Application”Project;
2. 添加头文件“StdAfx.h”,内容是 #include <afxwin.h>
3. 添加源文件“StdAfx.cpp”,内容是 #include "StdAfx.h"
4. 执行Build,会看到LinkError,打开Project|Setting,在General里,选择“Use MFC in Shared DLL”,再次执行Build,一切OK。WinMain内嵌在MFC的链接库里。
5. 按F5调试执行,会出现一个“Unhandled exception …”,通过CallStack可以找到原因:AfxGetThread()和AfxGetApp()返回的都是NULL。需要实现一个全局的CWinApp对象。
6. 添加一个新Class:“class CMyWinApp : public CWinApp”,头文件和源文件分别是Hello.cpp Hello.h,并在Hello.cpp里实例一个全局对象:CMyWinApp theApp。CWinApp只能实例一个对象,在其构造函数里加了ASSERT,防止多次实例。
7. Build之后,再按F5调试执行,程序一闪就结束了,也没有错误。在Output窗口里可以找到一句“Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.”,是因为没有主窗口,所以程序直接退出了。
8. 重载CWinApp::InitInstance,在里面直接m_pMainWnd = new CFrameWnd;是不行的,因为CFrameWnd的构造函数里没有调用Create,窗口不会被创建。
9. 在CMyWinApp::InitInstance()里写入Code:
BOOL CMyWinApp::InitInstance()
{
CFrameWnd *pMainFrame;
pMainFrame = new CFrameWnd;
pMainFrame->Create(NULL, "Hello MFC",
WS_OVERLAPPEDWINDOW, pMainFrame->rectDefault, NULL);
m_pMainWnd = pMainFrame;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
编译后运行,可以看到一个窗口:
即,可以直接使用MFC的CFrameWnd类实现一个窗口,但是CWinApp不能直接使用,必须派生一个用户类,因为Windows程序的启动顺序是:实例全局对象,WinMain,…,如果不实例CWinApp,找不到机会创建窗口,而派生之后,就可以重载CWinApp::InitInstance函数,AfxWinMain里会调用这个函数。
10. 使用File|New,选择Resource Script,添加一个资源文件,在资源文件里添加一个Menu,在Menu的Property的ID里填上MenuName字串"MainMenu",然后修改InitInstance:
BOOL CMyWinApp::InitInstance()
{
CFrameWnd *pMainFrame;
pMainFrame = new CFrameWnd;
pMainFrame->Create(NULL, "Hello MFC",
WS_OVERLAPPEDWINDOW, pMainFrame->rectDefault, NULL, "MainMenu");
m_pMainWnd = pMainFrame;
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
编译运行后就可以看到菜单了。如果Menu使用的整数ID,使用MAKEINTRESOURCE转换为字符串。
11. 到现在为止,因为直接使用的CFrameWnd,这个程序什么也不能干,要实现用户功能,我们要从CFrameWnd派生一个自己的类CMainFram,我打算在窗口里实现一个字符串从天而降的功能,即重载CFrameWnd::OnPaint函数。
12. 首先给CMainFram加上消息映射表,在类声明里加上DECLARE_MESSAGE_MAP(),在类实现文件里添加
BEGIN_MESSAGE_MAP(CMainFram, CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()
对于标准的Windows消息,其消息名称和消息函数都是固定的,而且CFrameWnd(或其基类)已经都实现了这些消息响应的虚函数,只要在BEGIN… END… 里写入消息映射描述,就会添加到消息映射表里。
注意,对于CView类来说,ON_WM_PAINT()在文件:C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC\ VIEWCORE.CPP的MESSAGE_MAP已经写好了,用户不用写,但对于CFrameWnd来说,必须写出来才能加到消息映射表里。
13. 实现函数OnPaint,就可以沿着Client区域画一个红色的矩形框。
void CMainFram::OnPaint()
{
CPaintDC dc(this);
RECT rect;
CPen *poOldPen;
CPen oNewPen(PS_SOLID, 1, RGB(255,0,0));
poOldPen = dc.SelectObject(&oNewPen);
GetClientRect(&rect);
dc.Rectangle(&rect);
dc.SelectObject(poOldPen);
}
14. 在Resource添加一个简单的对话框,添加一个OnAbout消息响应函数:
void CMainFram::OnAbout()
{
CDialog dlg(IDD_DIALOG_ABOUT, this);
dlg.DoModal();
}
点击Help|About时,就会弹出资源里的对话框,可见对于没有复杂控件的简单对话框,可以直接使用CDialog类,不需要派生。