《MFC教程》06章 字符串类CString


C语言的字符串即字符数组,在编程时时时要当心是否分配了足够的空间。用MFC中的CString来处理字符串,那些容易出错的麻烦事一概不存在,使用非常方便。

一、WinMain()函数在哪儿

MFC把千篇一律的WinMain()函数写在crtexec.c中,在编译完后链接时才组装到你的exe程序中。运行时,这个WinMain()函数调用MFC的全局函数AfxWinMain(),这个全局函数AfxWinMain()是写在appmodul.cpp中的。在AfxWinMain()函数中做三件事,注册窗口类、调用应用程序类的初始化函数InitInstance()、调用应用程序类的Run()函数(实际上是父类的父类CWinThread的Run()成员函数)。

上面这个Run()函数中包含消息循环,而InitInstance()函数又将框架类、文档类、视图类结合在一起,于是所有的类全部集成起来了。编程的重点在文档类和视图类,什么样的消息,执行什么样的处理函数,这样就有效地将数据和控制分离开来。

二、消息处理

消息处理的回调函数在mfc70d.dll中的CWnd::WindowProc(...),由上面讲的Run()函数调用,然后在主应用程序类、框架类、文档类、视图类里面接受这些消息并处理。问题是:某一消息究竟在哪个类里面处理?

与窗口有关的消息(即以“WM_”开头的消息),只能在框架类和视图类中处理;来自菜单或工具条的命令事件,则框架类、视图类、主应用程序类、文档类全部可以处理,究竟在哪个类中处理,根据具体情况再决定在哪个类中处理。这其中有优先级别高低的问题,一个类接受到命令消息时,先传给比自己级别高的类,如果未处理再自己处理。如果自己也不处理,则传给比自己级别低的类。

这个优先级别是:视图类>文档类>文档模板类>框架类>主应用程序类。例如,框架类收到“编辑”菜单的“Clear All”命令消息时,首先传给视图类,如果视图类处理便结束,否则就传给文档类。如果文档类处理便结束,否则就传给文档模板类。如果文档模板类处理则结束,否则就回到了框架类。如果框架类处理则结束,否则就传给主应用程序类。如果主应用程序类还不处理,就回到MFC缺省的处理程序中。

三、添加、删除消息处理

添加一个消息处理,一般要改动三个地方,以WM_LBUTTONDOWN消息为例,①在视图类的定义(test2View.h)中添加一个成员函数,②在视图类(test2View.c)中添加一条消息映射,③在视图类(test2View.c)中实现消息处理的成员函数。

// test2View.h : Ctest2View 类的接口

......(省略)

// 生成的消息映射函数
protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
};

......(省略)

// test2View.cpp : Ctest2View 类的实现
//

#include "stdafx.h"
#include "test2.h"

#include "test2Doc.h"
#include "test2View.h"
#include ".\test2view.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// Ctest2View

IMPLEMENT_DYNCREATE(Ctest2View, CView)

BEGIN_MESSAGE_MAP(Ctest2View, CView)
    // 标准打印命令
    ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

......(省略)

// Ctest2View 消息处理程序

void Ctest2View::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    AfxMessageBox("劝学网 http://www.quanxue.cn/", MB_OK);

    CView::OnLButtonDown(nFlags, point);
}

上面虽然很简单,但不建议手动添加,应该在“类视图”中选中“Ctest2View”,再在“属性”工具中选择“WM_LBUTTONDOWN”消息,同时选上“OnLButtonDown”后回车就可以了。

用同样方法在“属性”工具中删除“WM_LBUTTONDOWN”消息时,前面添加的三处代码将被用“//”注释在那儿,成了“垃圾”代码。这时最好手动删除一下这三处“垃圾”代码。

四、MFC特有的规则

类型:MFC将C++的关键字用宏定义成以下内容。

MFC类型意思C++类型
BOOL,BOOLEAN布尔型boolean
BYTE1字节数值型char
WORD2字节数值型short
DWORD4字节数值型int
UINT无符号整型unsigned int
VOIDvoid型void
LPDWORDDWORD的指针型int*
LPCSTR常量字符串const char*
LPSTR字符串char*
LPCVOID常量void指针const void*
LPVOIDvoid指针void*

常量:MFC将C++的常量用宏定义成以下内容。

MFC常量意思C++常量
NULL空指针0
TRUE布尔值:真true
FALSE布尔值:假false

命名规则:MFC有以下命名规则。

  1. 类名:以大写的C开头,单词的首字母大写,单词之间不用下划线。
  2. 成员函数和全局函数:以单词的首字母大写,单词之间不用下划线。全局函数前再加Afx
  3. 成员变量:匈牙利命名法,以“m_”开头,单词的首字母大写。
  4. 宏、类型名:全部使用大写。