我是荔园微风,作为一名在IT界整整25年的老兵,今天来聊聊MFC技术中消息的分类。
微软Windows中的消息虽然很多,但是种类并不繁杂,大体上有3种:窗口消息、命令消息和控件通知消息。
窗口消息
窗口消息是系统中最为常见的消息,它是指由操作系统和控制其他窗口所使用的消息。例如,CreateWindow、DestroyWindow和 MoveWindow。下面代码以MFC单文档程序Message为例。
框架类中创建工具栏与状态栏示例:MainFrm.cpp如下:
int CMainFrame::OnCreate (LPCREATESTRUCT lpCreatestruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct)==-1)
return -1;
//创建工具栏
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_GRIPPER|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_SIZE_DYNAMIC)||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; //创建失败
}
//创建状态栏
if(!m_wndStatusBar.Create(this)||!m_wndStatusBar.SetIndicators (indicators,sizeof (indicators)/sizeof (UINT)))
{
TRACEO ("Failed to create status bar\n");
return -1; //创建失败
}
return 0;
}
第5行中的m_wndToolBar.CreateEx()用来创建工具栏窗口,第14行的m_wndStatusBar.Create()用来创建状态栏窗口。
命令消息
命令消息是一种特殊的窗口消息,它一般与处理用户请求相关,当用户单击一个菜单项或工具栏时,命令消息产生,并被发送到能处理该请求的类对象。命令消息与窗口消息(除WM_COMMAND之外,前缀是WM_的消息)不同,窗口消息与某一窗口紧密相关,应该由接收消息的窗口来处理;而命令消息与具体的窗口无关,只是为本程序完成一个功能操作。
接下来以给视图类加入MouseMove()命令消息为例说明。
(1)在类视图中单击CMessageView,之后会在工程窗口的右上方看到消息添加功能键。如果给视图类添加命令消息,就必须单击视图,如果给框架类添加框架,就必须单击CMainFrame。 VS2005及其以后版本则不同于VC++6.0。在VC++6.0中右击就会出现“Add windows Message Handle...”选项。
(2)单击消息添加功能键第5个按钮,就会在下方看到各种命令消息。
(3)在各种命令消息界面中单击选项“<Add>OnMouseMove”后,在MessageView.cpp中就会自动生成代码,如下面代码所示。至此完成了按钮控件消息的添加。
视图类中的命令消息示例:MessageView.cpp
void CMessageView::OnMouseMove (UINT nFlags, CPoint point)
{
//可以在这里添加你自己的代码
CView::OnMouseMove(nFlags, point);
}
代码可以实现视图窗口中关联光标移动的命令消息。大家可以在第3行添加自己的代,以实現不同的功能。当光标移动时产生一个命令消息传递给视图口。此命消息在视图类的消息映射表现形式如下代码第6行:
BEGIN_MESSAGE_MAP(CMessageView, CView)
// Standard printing commands
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_MOUSEMOVE()
END_MESSAGE_MAP()
控件通知消息
控件通知消息用于当一个窗口内的子控件发生了一些事情需要通知父窗口。通知消息只适用于标准的窗口控件(如按钮、编辑框、单选框)以及Windows公共控件(如树状视图、列表视图等)。
例如,单击或双击一个控件、操作控件的滚动条、在控件中选择文本都会产生通知消息。当用户与控件窗口交互时,那么控件通知消息就会从控件窗口发送到它的主窗口。但这种消息并不是为了处理用户命令,而是让主窗口能够实时改变控件的状态,例如加载资源、显示数据。例如滑动一个滚动条,它向父窗口发送的消息可以看作是一个控件通知消息。
窗口消息及控件通知消息主要由窗口类来处理。相对于这两个消息,命令消息的处理对象范围就广得多,它不仅可以由窗口类处理,还可以由文档类、文档模板类及应用类所处理。
对于控件通知消息,本文只列举如下几个常用控件的常用通知消息:
按钮控件
BN_CLICKED:用户单击了按钮。
BN_DOUBLECLICKED:用户击了按钮。
BN_ KILLFOCUS:按钮失去了输入焦点。
BN_SETFOCUS:钮获得输入焦点。
BCN_HOTITEMCHANGE:高亮的条目被改变
NM_THEMECHANGED:主题被改变。
编辑框控件
EN_CHANGE:编辑框中的文本已更新。
EN_ERRSPACE:编辑框内存不足。
EN_HSCROLL:用户单击了水平滚动条。
EN_ KILLFOCUS:编辑框正在失去输入焦点。
EN_MAXITEXT:插的内容被断。
EN_SETFOCUS:编辑框获得输入焦点。
EN_UPDATE:编辑框中的文本将要更新。
EN_VSCROLL:用户单击了垂直滚动条消息含义。
EN_ALIGN_LTR_EC:用户从左到右改变了编辑框的方向。
EN_ALIGN_RTL_EC:用户从右到左改变了编辑框的方向。
组合框控件
CBN_SELCHANGE:在组合框中选择了一项。
CBN_EDITCHANGE:用户修改了编辑框中的文本。
CBN_CLOSEUP:组合框的列表框被关闭。
CBN_DBLCLK:用户双击了一个字符串。
CBN_DROPDOWN:组合框的列表框被拉出。
CBN_EDITUPDATE:编辑框内的文本即将更新。
CBN_ERRSPACE:组合框内存不足。
CBN_KILLFOCUS:组合框推动输入焦点。
CBN_SELENDCANCEL:用户的选择应当被取消。
CBN_SELENDOK:用户的选择是合法的。
CBN_SETFOCUS:组合框获得输入焦点。
首先新建一个基于对话框的 MFC工程 MFC_message,然后在对话框上添加了一个按钮,命名为“确定”。要实现单击此按钮完成相应的功能。因此控件通知消息的类型为BN_CLICKED。具体实现步骤如下:
(1)在资源视图中右击“确定”按钮控件,出现菜单有一项叫添加事件处理程序。给按钮添加消息命令,直接双击此按钮即可。但此种做法有个缺点,就是控件消息响应函数的名字只能是系统默认的,不能随意改变。
(2)选择菜单中的“添加事件处理程序..”命令后,出现新的画面。
(3)在“消息类型”列表框中选择BN_CLICKED选项,“类列表”选项默认为CMFC_MessageDlg,此处不变。在“函数处理程序名称”列表框中可以为按钮的单击事件响应函数命名,因此大家可以随便取名。之后单击右下方第一个“添加编辑”按钮即可。以上3步完成后,系统会在文件中自动生成如下代码:
头文件 MFC_MessageDlg.h
afx_msg void OnBnClickedOk();
源件MFC_MessageDlg.cpp:
按钮控件单击消息映射表现形式如下代码6行:
BEGIN_MESSAGE_MAP (CMEC_MessageDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDOK, &CMFC_MessageDlg::OnBnClickedOk)
END_MESSAGE_MAP()
而具体函数定义体如下:
视图类中的命令消息示例:MFC_MessageDlg.cpp
void CMFC_MessageDlg::OnBnClickedOk()
{
//可以在此添加你自己的按钮控制消息
OnOK();
}
由上面定义体可知,当单击“确定”按钮时,就会关闭对话框。如果你想改变此功能,可以从第4行开始写入新的代码。
作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。