当前位置:松语文学 > 其他类型 >VC++_6.0程序设计从入门到精通最新章节 > VC++_6.0程序设计从入门到精通TXT下载
错误举报

第 13 章

  2)在类的实现文件中加入消息映shè表:

  BEGIN_MESSAGE_MAP(类名, 父类名)

  ??

  消息映shè表项

  ??

  END_MESSAGE_MAP()

  在CTestApp 类的实现文件TestApp.cpp 的开头、常量定义的后面,就有如下消息映shè表

  的代码:

  /////////////////////////////////////////////////////////////////////////////

  枫叶文学网www.fywxw.com

  Visual C++ 6.0 程序设计从入门到精通

  ·44·

  // CTestApp

  BEGIN_MESSAGE_MAP(CTestApp, CWinApp)

  //{{AFX_MSG_MAP(CTestApp)

  ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

  // NOTE - the ClassWizard will add and remove mapping macros here.

  // DO NOT EDIT what you see in these blocks of generated code!

  //}}AFX_MSG_MAP

  // Standard file based doccomnt commands

  ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)

  ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)

  // Standard print setup command

  ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)

  END_MESSAGE_MAP()

  MFC AppWizard 生成的应用程都已经自动包含消息映shè的代码,但用户也可以在源程序

  中手动添加。同时Visual C++另一个强大的工具ClassWizard 也提供了处理消息映shè表的自动

  化机制。当然,ClassWizard 只能够生成类和消息处理的框架,包括创建消息处理函数的声明,

  而具体的实现代码还需要用户去补充。

  在类中,消息处理函数都是类的成员函数。当程序要对一个消息进行响应时,消息映shè

  机制就会自动调用该函数。用ClassWizard 添加消息处理函数时,会自动添加以下3 部分内

  容:

  ? 在类的定义中添加该消息处理成员函数的函数声明;

  ? 在类的消息映shè表中加入相应的消息映shè表项;

  ? 在类的实现中加入该消息处理成员函数的函数实现。

  注意ClassWizard 添加的函数实现中,只是一个不能完成任何cāo作的空函数框架,还需

  要加入具体的实现代码。但当用户手动添加消息处理函数时,也必须添加上述3 部分内容。

  对于标准Windows 消息,在CWnd 类中已经预定义了默认的处理函数,有确定的函数名,

  一般以On 开头,以消息名为函数名的后半部分,例如WM_PAINT 消息的处理函数为

  OnPaint(),WM_CREATE 消息处理函数是OnCreate()。这些预定义的消息处理函数根据消息

  的不同有不同的参数和返回值。

  对于控件通知消息和命令消息,一般没有默认的消息处理函数,可以由用户自定义。MFC

  建议这类函数命名应遵循一些约定,一般以On 开头,函数名中应包含该消息的简要说明,

  方便阅读代码。ClassWizard 在创建这类消息处理函数时会提供一个建议的函数名,一般无需

  修改。例如OnFileOpen()函数表明处理命令标识符ID_FILE_OPEN 的命令消息。

  本章和以后的章节都将主要利用ClassWizard 为程序添加消息处理函数。因此下面简要

  介绍一下ClassWizard 对话框,如图3-1 所示。在IDE 主菜单栏中选择“View|ClassWizard”

  菜单命令,或者在开发环境的界面中直接按快捷键Ctrl+W,即可打开“MFC ClassWizard”

  对话框。选择“Message Maps”的选项卡,即可进行编辑消息映shè的设置。

  枫叶文学网www.fywxw.com

  第3 章 菜单与加速键

  ·45·

  图3-1 消息映shè选项卡

  ClassWizard 对话框的“Message Maps”(消息映shè)选项卡中的各项功能介绍如下:

  ? Project(工程)下拉列表框:用于选择需要编辑的工程名称。

  ? Class ncom(类名)下拉列表框:用于选择需要编辑消息映shè的类的名称。选择好类

  后,在该下拉列表框 和“Project”下拉列表框的下一行将显示所选类的头文件和源文

  件路径。

  ? Object IDs(对象ID)列表框:以列表形式显示可以产生消息的对象的ID,包括菜单

  项、按钮等的ID。该列表框的第一项总是显示所选择的类。

  ? Messages(消息)列表框:列举在“Object IDs”列表框中选定的对象所能产生的各种

  消息。

  ? Member functions(成员函数)列表框:以列表形式显示选定的类中的成员函数。该列

  表框中只列出与消息处理函数以及MFC 中与消息处理有关的虚函数。前者标记为

  “W”,并在函数名后显示对应的消息映shè宏;后者标记为“V”。

  ? Add Class(添加类)按钮:单击该按钮,添加新的类到工程中。该按钮在“MFC

  ClassWizard”对话框中的所有选项卡中都存在。

  ? Add Function(添加函数)按钮:单击该按钮添加选定消息的新的消息处理函数,包

  括在消息映shè定义中添加对应的宏指令,在选定的类中添加该消息处理函数的声明和

  完成基本功能的代码实现。如果选定的消息已经有消息处理函数,则该按钮无效。对

  于对象产生的消息,单击该按钮将弹出如图3-2 所示的对话框,要求用户输入消息处

  理函数的名称,在“Member function ncom”(成员函数名称)输入框中输入函数名,

  确定后ClassWizard 就会自动添加该消息处理函数。对于由该选定的类产生的消息,

  MFC 已经定义好了消息处理函数名称,单击“Add Function”按钮将直接添加该消息

  处理函数,不会提示用户输入自定义的函数名。注意,只有单击“MFC ClassWizard”

  的“OK”按钮或者“Edit Code”按钮退出“MFC ClassWizard”对话框后,ClassWizard

  才会真正修改源文件。

  枫叶文学网www.fywxw.com

  Visual C++ 6.0 程序设计从入门到精通

  ·46·

  图3-2 添加消息处理函数的对话框

  ? Delete Function(删除函数)按钮:单击该按钮删除选定消息的消息处理函数,包括函

  数的声明和定义该消息映shè的宏语句。如果选定的消息没有消息处理函数,则该按钮

  无效。注意,当该函数已经存在于源文件中时,单击该按钮会提示如图3-3 所示的对

  话框,告诉用户ClassWizard 只能删除该函数的声明和定义该消息映shè的宏语句,而

  无法删除该函数的实现代码,用户需要手动删除。

  图3-3 提示用户手动删除消息处理函数的对话框

  ? Edit Code(编辑代码)按钮:单击该按钮退出“MFC ClassWizard”对话框,同时IDE

  的代码编辑窗口直接转到选定消息的处理函数进行编辑。该按钮也使得在“MFC

  ClassWizard”中所做的更改生效。如果选定的消息没有消息处理函数,则该按钮无效。

  ? OK(确定)按钮:单击该按钮使得在“MFC ClassWizard”中的编辑生效,并退出“MFC

  ClassWizard”对话框。

  ? Cancel(取消)按钮:单击该按钮取消所有“MFC ClassWizard”对话框中的设置,并

  退出“MFC ClassWizard”对话框。

  3.1.3 消息处理过程

  在Windows 程序设计中,消息的处理是通过消息循环进行接收与分发的。MFC 运用消

  息映shè机制封装了这一处理过程。下面介绍MFC 中消息的处理过程。

  1.标准Windows 消息和控件通知消息

  标准Windows 消息和控件通知消息的处理过程比较简单。这类消息必须由CWnd 或其派

  生类的对象处理,消息传递到封装对应的窗口或子窗口的类的对象中。也就是说,当关闭程

  序的时候,会产生一个WM_CLOSE 消息并通知主框架类,主框架类调用相应的处理函数进

  行程序关闭前的清理cāo作,如保存文件和数据等。

  2.命令消息

  命令消息与其他两个类型的消息不同,它可以由应用程序其他类的对象(例如应用类对

  象、文档对象和文档模板对象)处理。这就涉及一个消息传递路径的问题,具体来说就是允

  枫叶文学网www.fywxw.com

  第3 章 菜单与加速键

  ·47·

  许一个还是多个对象处理该消息、允许哪些对象处理等。MFC 中采取了简单的方法,只允许

  其中一个对象处理该消息,当沿着消息传递路径找到第一个包含该消息的处理函数的对象时,

  则处理该消息,然后中断传递过程,不再搜索后续的对象。

  由于命令消息可以被多种类的对象处理,因此命令消息的传递路径比较复杂,但总体思

  想是由子窗口到父窗口,由窗口到文档。下面举一个简单的例子。

  假设是一个多文档MDI 应用程序,用户触发了“编辑”菜单下的“粘贴”菜单项的命令

  消息,此时消息依照以下顺序传递。

  (1)MDI 主框架窗口首先收到此命令消息。

  (2)主框架将处理命令的机会先让给其当前活动的MDI 子框架窗口。

  (3)子框架窗口又将处理该命令的机会让给其活动的视图。

  (4)视图先搜索自己的消息映shè,寻找对应的处理函数,如果没找到,则将消息传递给

  与其关联的文档,找到则调用并中止传递过程。

  (5)文档搜索自己的消息映shè,寻找对应的处理函数。一般情况下文档中包含“粘贴”

  消息的处理函数,调用该处理函数完成粘贴功能。如果没有找到,文档将消息传递给文档模

  板。

  (6)文档模板进行相同的过程,如果没找到,将消息传递回子框架窗口。

  (7)子框架窗口搜索对应的处理函数,如果没找到,则将消息传回MDI 主框架窗口。

  (8)如果主框架窗口中也没找到,则消息最后停留在应用对象,不再进行进一步的传递。

  从上面的叙述可以看出,命令消息的传递过程很复杂。然而一般情况下不需要了解这么

  详细的消息传递路径,只需根据完成功能的要求,在相应的类中添加实现代码,就不会产生

  冲突,比如例子中提到的粘贴功能,一般就是由文档完成的,因此只需在文档类中添加这个

  命令消息的处理函数,而不必在别的类中添加与

  松语文学免费小说阅读_www.16sy.com