侯捷先生《深入浅出MFC》一书已经成书十余年了,当时用的还是VC6.0,而现在大多数人用的都是从VS2010到VS2015这些版本。今年刚毕业的我进入公司学习使用MFC,就是用的VS2012.与侯捷先生《深入浅出MFC》书中的东西相比,有了不小的变化,现在我来说说自己这两天改写“Hello, MFC”代码的心得。
首先我完全按书上的打代码,一堆错误,然后我一句一句在网上找,改正后,成了下面代码:
resource.h:
//resource.h
#define IDM_ABOUT 100\n
hello.rc:
//hello.rc
#include "Resource.h"
#include "afxres.h"
JJHouRIcon ICON DISCARDABLE "JJHOUR.ico"
AFX_IDI_STD_FRAME ICON DISCARDABLE "JJHOUR.ico"
MainMenu MENU DISCARDABLE
{
POPUP "&Help"
{
MENUITEM "&About HelloMFC...", IDM_ABOUT
}
}
AboutBox DIALOG DISCARDABLE 34, 22, 147, 55
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Hello"
{
ICON "JJHouRIcon",IDC_STATIC,11,17,18,20
LTEXT "Hello MFC 4.0",IDC_STATIC,40,10,52,8
LTEXT "Copyright 1996 Top Studio",IDC_STATIC,40,25,100,8
LTEXT "J.J.Hou",IDC_STATIC,40,40,100,8
DEFPUSHBUTTON "OK",IDOK,105,7,32,14,WS_GROUP
}
stdafx.h:
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
#include <afxwin.h> // MFC 核心组件和标准组件
#include <afxext.h> // MFC 扩展
#include <afxdisp.h>
stdafx.cpp :
// stdafx.cpp : 只包括标准包含文件的源文件
// MFCApplication2.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
Hello.h:
class CMyWinAPP : public CWinApp
{
public:
BOOL InitInstance();
};
//----------------------------------------------------------------
class CMyFrameWnd : public CFrameWnd
{
public:
CMyFrameWnd();
afx_msg void OnPaint();
afx_msg void OnAbout();
private:
DECLARE_MESSAGE_MAP()
static VOID CALLBACK LineDDACallback(int,int,LPARAM);
};
Hello.cpp:
#include "stdafx.h"
#include "Hello.h"
#include "Resource.h"
CMyWinAPP theApp; //application object
//----------------------------------------------------------------
// CMyWinAPP's member
//----------------------------------------------------------------
BOOL CMyWinAPP::InitInstance()
{
m_pMainWnd = new CMyFrameWnd();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
//----------------------------------------------------------------
// CMyFrameWnd'smember
//----------------------------------------------------------------
CMyFrameWnd::CMyFrameWnd()
{
Create(NULL, _T("Hello MFC"), WS_OVERLAPPEDWINDOW, rectDefault,
NULL, _T("MainMenu")); //"MainMenu"定义于RC档
}
//----------------------------------------------------------------
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
ON_COMMAND(IDM_ABOUT,OnAbout)
ON_WM_PAINT()
END_MESSAGE_MAP()
//----------------------------------------------------------------
void CMyFrameWnd::OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect(rect);
dc.SetTextAlign(TA_BOTTOM | TA_CENTER);
::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2,
(LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc);
}
//----------------------------------------------------------------
VOID CALLBACK CMyFrameWnd::LineDDACallback(int x, int y, LPARAM lpdc)
{
WCHAR szText[] =L"Hello, MFC";
((CDC*)lpdc)->TextOutW(x,y,szText,sizeof(szText)-1);
for(int i=1; i<50000; i++); //纯粹是为了延迟下降速度,以利观察
}
//----------------------------------------------------------------
void CMyFrameWnd::OnAbout()
{
CDialog about(_T("AboutBox"), this); //"AboutBox"定义于RC档
about.DoModal();
}
调试结果如下:
1>------ 已启动生成: 项目: MFCApplication2, 配置: Debug Win32 ------
1> Hello.cpp
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(27): error C2017: 非法的转义序列
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(27): error C2146: 语法错误: 缺少“}”(在标识符“n”的前面)
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(27): error C2146: 语法错误: 缺少“;”(在标识符“n”的前面)
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(27): error C2065: “n”: 未声明的标识符
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(27): error C3867: “CMyFrameWnd::OnAbout”: 函数调用缺少参数列表;请使用“&CMyFrameWnd::OnAbout”创建指向成员的指针
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(27): error C2143: 语法错误 : 缺少“;”(在“}”的前面)
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(27): error C2059: 语法错误:“,”
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(28): error C2143: 语法错误 : 缺少“;”(在“{”的前面)
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(28): error C2447: “{”: 缺少函数标题(是否是老式的形式表?)
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(28): error C2059: 语法错误:“,”
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(29): error C2143: 语法错误 : 缺少“;”(在“{”的前面)
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(29): error C2447: “{”: 缺少函数标题(是否是老式的形式表?)
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(29): error C2059: 语法错误:“}”
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(29): error C2653: “TheBaseClass”: 不是类或命名空间名称
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(29): error C2065: “GetThisMessageMap”: 未声明的标识符
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(29): error C2065: “_messageEntries”: 未声明的标识符
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(29): error C2059: 语法错误:“return”
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(32): error C2143: 语法错误 : 缺少“;”(在“{”的前面)
1>c:\users\john\documents\visual studio 2012\projects\mfcapplication2\mfcapplication2\hello.cpp(32): error C2447: “{”: 缺少函数标题(是否是老式的形式表?)
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
错误在ON_COMMAND(IDM_ABOUT,OnAbout)
ON_WM_PAINT()
END_MESSAGE_MAP()
用//注释掉ON_COMMAND(IDM_ABOUT,OnAbout)
出现结果
注释掉
ON_COMMAND(IDM_ABOUT,OnAbout)
ON_WM_PAINT()
两行,那干脆就不出字了
把这三行连之上那行一起注释掉,就出新错误了
错误为:
resource.h:
//resource.h
#define IDM_ABOUT 100\n
多了个\n所以什么都不做直接调试会出错
用sizeof(szText)-1显示"Hello, MFC"是宽字符,有22个字符,而“Hello, MFC”本身只有10个字符,剩下的12个字符随机取一些东西,所以是乱码。。。改成wcslen(szText)就好
for(int i=1; i<50000; i++); 减缓下降速度不好用,要改成::Sleep(100);才好。。。
所以最后代码应该是:
resource.h:
//resource.h
#define IDM_ABOUT 100
hello.rc:
//hello.rc
#include "Resource.h"
#include "afxres.h"
JJHouRIcon ICON DISCARDABLE "JJHOUR.ico"
AFX_IDI_STD_FRAME ICON DISCARDABLE "JJHOUR.ico"
MainMenu MENU DISCARDABLE
{
POPUP "&Help"
{
MENUITEM "&About HelloMFC...", IDM_ABOUT
}
}
AboutBox DIALOG DISCARDABLE 34, 22, 147, 55
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Hello"
{
ICON "JJHouRIcon",IDC_STATIC,11,17,18,20
LTEXT "Hello MFC 4.0",IDC_STATIC,40,10,52,8
LTEXT "Copyright 1996 Top Studio",IDC_STATIC,40,25,100,8
LTEXT "J.J.Hou",IDC_STATIC,40,40,100,8
DEFPUSHBUTTON "OK",IDOK,105,7,32,14,WS_GROUP
}
stdafx.h:
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
#include <afxwin.h> // MFC 核心组件和标准组件
#include <afxext.h> // MFC 扩展
#include <afxdisp.h>
stdafx.cpp :
// stdafx.cpp : 只包括标准包含文件的源文件
// MFCApplication2.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
Hello.h:
class CMyWinAPP : public CWinApp
{
public:
BOOL InitInstance();
};
//----------------------------------------------------------------
class CMyFrameWnd : public CFrameWnd
{
public:
CMyFrameWnd();
afx_msg void OnPaint();
afx_msg void OnAbout();
private:
DECLARE_MESSAGE_MAP()
static VOID CALLBACK LineDDACallback(int,int,LPARAM);
};
Hello.cpp:
#include "stdafx.h"
#include "Hello.h"
#include "Resource.h"
CMyWinAPP theApp; //application object
//----------------------------------------------------------------
// CMyWinAPP's member
//----------------------------------------------------------------
BOOL CMyWinAPP::InitInstance()
{
m_pMainWnd = new CMyFrameWnd();
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
return TRUE;
}
//----------------------------------------------------------------
// CMyFrameWnd'smember
//----------------------------------------------------------------
CMyFrameWnd::CMyFrameWnd()
{
Create(NULL, _T("Hello MFC"), WS_OVERLAPPEDWINDOW, rectDefault,
NULL, _T("MainMenu")); //"MainMenu"定义于RC档
}
//----------------------------------------------------------------
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
ON_COMMAND(IDM_ABOUT,OnAbout)
ON_WM_PAINT()
END_MESSAGE_MAP()
//----------------------------------------------------------------
void CMyFrameWnd::OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect(rect);
dc.SetTextAlign(TA_BOTTOM | TA_CENTER);
::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2,
(LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc);
}
//----------------------------------------------------------------
VOID CALLBACK CMyFrameWnd::LineDDACallback(int x, int y, LPARAM lpdc)
{
WCHAR szText[] =L"Hello, MFC";
((CDC*)lpdc)->TextOutW(x,y,szText,wcslen(szText));
::Sleep(100);
//for(int i=1; i<50000; i++); //纯粹是为了延迟下降速度,以利观察
}
//----------------------------------------------------------------
void CMyFrameWnd::OnAbout()
{
CDialog about(_T("AboutBox"), this); //"AboutBox"定义于RC档
about.DoModal();
}
这个程序我纠结了好久,总算是成功了。