返回 1
第六章 菜单、工具栏和状态栏本章导读掌握菜单的创建步骤和方法,如何进行命令消息的映射和编写相应的程序代码 。
掌握 CMenu类及其常用成员函数的功能和使用方法,掌握利用这些成员函数创建快捷菜单和实现动态增加或减少菜单项 。
掌握工具栏的创建方法和步骤,如何将工具栏的功能与菜单的功能相对应 。
掌握创建状态栏的方法和步骤 。
学习和掌握 CMenu类,CStatusBar类,CToolBar类,
CCmdUI类及常用成员函数的功能和使用 。
菜单,工具栏和状态栏是 Windows应用程序中最重要的三个用户界面元素,是应用程序设计中不可缺少的步骤 。
返回 2
6.1 创建菜单菜单是一系列命令的列表,是最常用的命令输入方式 。
在 Windows中,几乎所有的命令操作都与菜单有关 。
Windows应用程序中的菜单是按照一定层次来进行组织的,包括菜单项和弹出菜单,其中弹出菜单又可以包括菜单项和其他的弹出菜单。
1.创建菜单资源菜单中的每一个菜单项都由 菜单项名 和 命令 ID号 两个基本要素组成 。 在菜单资源中,每个菜单项都必须有一个唯一的命令 ID号来对它进行标识,这个 ID号是系统在对菜单项进行识别时使用的 。 对于用户而言,菜单项的标识是利用它所属的弹出菜单和菜单项的句子来标识的,
比如 ID_FILE_OPEN,其所属的弹出菜单是 【 文件 】,菜单项名称为 【 打开 】 。
返回 3
创建菜单可以有几种方法,最简单的方法是用菜单资源编辑器进行设计 。 在这里,我们把第五章关于模式对话框的例子进行改造,使对话框的弹出方式由在窗口中双击鼠标改为由单击某个菜单命令实现 。 具体步骤如下:
步骤一,在 Visual C++ 6.0中,选 【 File】 菜单中的 【 Open
Workspace】 菜单项,打开已创建的,Dialog.dsw” 文件 。
步骤二,在工作区窗口中选择 【 Resource View】 选项卡,
展开 【 Dialog Resources】 目录,再展开 【 Menu】 文件,将会看到菜单 IDR_MAINFRAME。
步骤三,双击 IDR_MAINFRAME,将在菜单资源编辑器中打开菜单资源。
步骤四,在主菜单中增加一个 【 显示 】 菜单。用鼠标双击主菜单最右边的空菜单项,或者用鼠标右击,在弹出的快捷菜单中选择 【 Properties】 菜单项。系统将弹出属性对话框。
返回 4
在 【 Caption】 栏中输入,显示 ( &P),,括号中的 &P表示紧跟在它后面的字母,P” 是助记符,这样,在程序运行过程中,就可以用 Alt+P键来激活 【 显示 】 菜单 。 按
【 Enter】 键继续 。
这时,在主菜单中将增加一个,显示,菜单,在助记符
P下面有下划线 。 同时,在生成的菜单的右面和下面各出现一个新的菜单或菜单项,可以继续添加新的菜单或菜单项 。
步骤五,在 【 显示 】 菜单中增加一个 【 个人资料 】 菜单项 。 用鼠标右键单击 【 显示 】 菜单中的空菜单项,在弹出菜单中选择 【 Properties】 选项 。 单击属性对话框左上角的,图钉,按钮,把对话框,钉,在屏幕上 。 在属性对话框的 【 Caption】 栏中输入,个人资料 ( &D),。
返回 5
对于 【 个人资料 】 菜单项,Visual C++ 6.0将为该菜单项自动分配一个 ID号 。 单击其他菜单项或者屏幕的其他部分,再选中 【 个人资料 】 菜单项,系统在 【 ID】 栏中显示 出 为 该 菜 单 项 分 配 的 ID 号,其 一 般 格 式 为
MENUITEMxxxxx(xxxxx代表一个整数 )。 【 Prompt】 框中的文本是光标处于菜单项时,状态栏显示的帮助信息在菜单项属性对话框的 【 General】 选项卡中,各选项的含义如下图所示 。
步骤六,用鼠标左键按住 【 显示 】 菜单,将其拖到 【 编辑 】 与 【 帮助 】 菜单中间 。
这样,利用菜单资源编辑器,我们就很轻松地创建了一个标准的 Windows菜单。
返回 6
项目 含义
ID
Caption
Separator
Checked
Pop_up
Grayed
Inactive
Help
Break
Prompt
菜单的资源 ID号菜单项的标题文本,当其中某一字母的前面含有 &符号时,则该字母与 Alt键构成组合键选中时,则相应的菜单项是一个分隔符或一条水平线选中时,则相应的菜单项前显示一个选中标记,√,
选中时,表示该菜单项含有弹出式子菜单选中时,表示该菜单项呈灰色显示,该菜单项被禁用选中时,表示该菜单项没有被激活,用户不能选用选中时,表示该菜单项在程序运行时被放于顶层菜单的最右端其默认值为 None,表示菜单项按常规形式显示 。 该项的取值还可为 Column或 Bar,
指明当光标移到该菜单项时在状态栏上显示的提示表 6.1 菜单 General属性对话框的各项含义返回 7
2,建立快捷键在 Windows应用程序中的某些菜单项后面有一个组合键,
表示一个快捷键 ( shortcut key),在程序运行过程中,
如果用户按下了该组合键,则相应的菜单命令就会被执行 。 当然,若要使用快捷键选择某个菜单项,就必须事先对其作出定义 。 现在我们来为刚才创建的菜单添加快捷键,具体步骤如下:
步骤一,在工作区窗口的 【 Resource View】 选项卡中,
双击 【 Accelerator】 文件夹,双击 IDR_MAINFRAME,
则系统会弹出一个加速器表 。
步骤二,在加速器表中浏览一下,发现 Ctrl+D还没有被使用,我们就把 Ctrl+D设置为菜单项 【 个人资料 】 的快捷键 。
方法是双击加速器表末尾的空行,将弹出快捷键的属性对话框 ( Accel Properties) 。
返回 8
在属性对话框 ( Accel Properties) 中,各项的含义如表 6.2所示 。
表 6.2 Accel Properties对话框中各选项的含义选项 含义
ID
Modifiers
Type
Key
Next Key
Typed
为了能使设定的快捷键与某个菜单项的功能相对应,从中选择所需的菜单资源 ID号用来选择 Ctrl,Alt,Shift键是否为快捷键的组成键用来确定快捷键的值是虚拟键 (VirKey)还是 ASCII
是指启动快捷键的键盘按键单击此按钮时,用户所按的任何按键将成为快捷键的键值返回 9
步骤三,在对话框中的 【 ID】 下 拉 列 表 中 选 择
【 ID_DISPLAY_DATA】 选项,当选中 ID号时,【 ID】
框 中 同 时 显 示 出 此 ID 号 对 应 的 整 数,如
ID_DISPLAY_DATA=32771。
步骤四,在 【 Key】 列表框中输入,D”,确认
【 Modifiers】 栏中的 【 Ctrl】 复选框被选中,而且 【 Alt】
和 【 Shift】 都未被选中;或者,直接单击 【 Next Key
Typed】 按钮,按下 Ctrl+D组合键放开,此时系统会自动记录所按下的 Ctrl+D键为所要设定的组合键 。 按 【 Enter】
键继续 。
步骤五,为了在 【 显示 】 菜单中提示 【 个人资料 】 菜单项的快捷键,可以返回 6.1.1节中的步骤五,将 【 Caption】
框中的内容修改为,个人资料 (D)\tCtrl+D” 。
这样,我们就建立了一个完整的菜单资源 。
返回 10
3 菜单功能的实现在 MFC框架中,菜单命令消息是按照一定的 顺序 进行传递的 。 对于一个单文档应用程序,消息传递的顺序为:
视图类 → 文档类 → 框架类 → 应用程序类 。 因此,如果我们在视图类和文档类中同时定义了某个菜单项的消息映射接口时,由于消息首先传递给视图类,在视图类中对此消息做出了响应,所以,文档类中定义的此菜单项的消息映射函数就无法执行 。
在菜单资源中,我们定义了 MFC如何来构造菜单的结构,同 时 还 指 定 了 菜 单 的 资 源 ID 号,MFC 通过
ClassWizard会自动把菜单和相应的框架窗口联系在一起 。
但除了由系统产生的少量代码外,MFC不能自动地对程序的菜单项进行响应,必须用手工实现 。
返回 11
对于每个菜单项,系 统 提 供 了 COMMAND 和
UPDATE_COMMAND_UI两种消息可供选择:
( 1) COMMAND消息需要用户的干预,如单击,双击等操作;
( 2) UPDATE_COMMAND_UI消息系统会自动进行响应,
通过它可以实现对菜单项外观的动态管理 。 例如,设计人员可以使菜单有效,无效或给菜单项动态添加检查标记等 。
可以利用 ClassWizard同时设置这两种消息,但是在实际编程中,必须为每个菜单项提供有关 WM_COMMAND
类型消息映射接口 。
下面,我们在视图类中对前面已建立的,个人资料
( &D),菜单项的消息做出响应 。 具体步骤如下:
返回 12
步骤一,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
弹出 【 MFC ClassWizard】 对话框 。
步骤二,在 【 MFC ClassWizard】 对话框中,选择
【 Message Maps】 选项卡 。 在 【 Class name】 下拉列表框中,选择类 CDialogView;在 【 Object Ids】 中单击选择
ID_DISPLAY_DATA 选项;在 【 Messages】 栏中将出现
COMMAND和 UPDATE_COMMAND_UI两个选项,选中其中的 COMMAND。
步骤三,单击对话框右侧的 【 Add Function】 按钮,系统将会弹出 【 Add Member function】 对话框 。 系统将自动生成一个缺省名称为 OnDisplayData的映射函数亦可另取别的名称,在此取缺省名称,单击 【 OK】 按钮继续 。
步骤四,单击 【 Edit Code】 按钮退出 【 MFC ClassWizard】
对话框,并编辑新增加的函数 OnDisplayData。
返回 13
经过以上操作完成后,Visual C++会对程序中的一些程序文件的代码进行必要的修改,其中粗体部分的代码是由 ClassWizard自动添加的代码 。
1,在 CDialogView类的定义文件 DialogView.h中的消息映射部分将会改变为:
// Generated message map functions
protected:
//{{AFX_MSG(CDialogView)
afx_msg void OnLButtonDblClk(UINT nFlags,CPoint point);
afx_msg void OnDisplayData(); //ClassWizard自动添加的
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
返回 14
其中:
//{{AFX_MSG(CDialogView)
//}}AFX_MSG
是 ClassWizard分别用来识别命令消息处理函数定义的起始标记和结束标记,在 AFX_MSG(CDialogView)后面括号内的 CDialogView表示是处理该消息的类 。
2,在 CDialogView类的实现文件 DialogView.cpp中的消息映射部分也进行了一些修改:
BEGIN_MESSAGE_MAP(CDialogView,CView)
//{{AFX_MSG_MAP(CDialogView)
返回 15
ON_WM_LBUTTONDBLCLK()
ON_COMMAND(ID_DISPLAY_DATA,
OnDisplayData) //ClassWizard自动添加的
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
其中:
//{{AFX_MSG_MAP(CDialogView)
//}}AFX_MSG_MAP
是 ClassWizard标识命令消息处理映射机制的起始标记和结束标记 。
返回 16
3,在 DialogView.cpp文件中编写 OnDisplayData函数的代码 。
把 DialogView.cpp 文 件 中 响 应 双 击 窗 口 的 函 数
OnLButtonDBLCLK()的代码复制到 OnDisplayData()函数中,具体代码如下:
void CDialogView::OnDisplayData()
{// TODO,Add your command handler code here
CMydataDialog dlg;
dlg.m_radio_m=0;
dlg.m_edit_name="";
CString msg;
if(dlg.DoModal()==IDOK)
{msg="<确定 >按钮被按下 ! "; }
Else {msg="<取消 >按钮被按下 ! ";}
返回 17
msg+="\r\n";
msg+="姓名,";
msg+=dlg.m_edit_name;
msg+="\r\n";
msg+="性别,";
switch(dlg.m_radio_m)
{case 0:msg+="男 ";
break;
case 1:msg+="女 ";
break; }
msg+="\r\n";
msg+="最高学历,";
msg+=dlg.m_combo_school;
msg+="\r\n";
msg+="爱好,";
返回 18
if(dlg.m_check_art==TRUE)
msg+="艺术 ";
if(dlg.m_check_music==TRUE)
msg+="音乐 ";
if(dlg.m_check_sport==TRUE)
msg+="体育 ";
AfxMessageBox(msg);
}
步骤五,编译运行并测试此应用程序。当选择 【 显示 】
菜单中的 【 个人资料 】 菜单项,或单击 Ctrl+D键时,将弹出 【 个人资料 】 对话框,在对话框内可以进行各种设置,
然后单击 【 确认 】 或 【 取消 】 按钮退出。可以看到其效果与双击应用程序窗口是一样的。
返回 19
4,CMenu类及其常用成员函数介绍
Visual C++的 MFC提供的菜单类 Cmenu的对象可以用来表示各种 Windows菜单,其中包括顶层菜单项及其相应的弹出式菜单。并且该类可以在程序运行时处理有关菜单的操作,如创建菜单、装入菜单、删除菜单项、获取或设置菜单项的状态等。
创建菜单
CMenu类的成员函数 CreateMenu和 CreatePopupMenu分别用来创建一个菜单或子菜单框架,其函数原型如下:
BOOL CreateMenu(); //产生一个空菜单
BOOL CreatePopupMenu(); //产生一个空弹出式子菜单返回 20
装入菜单
CMenu类的成员函数 LoadMenu可用来将菜单资源装入应用程序中,它的函数原型有两种,如下所示:
BOOL LoadMenu(LPCTSTR lpszResourceName);
BOOL LoadMenu(UNIT nIDResource);
其中:形参 lpszResourceName表示菜单资源的名称,形参
nIDResource为菜单资源的 ID号。
添加菜单项当菜单创建后,可以调用 CMenu类提供的成员函数
AppendMenu或 InsertMenu来向菜单中添加一些菜单项,
但每次添加时,函数 AppendMenu是将菜单项添加在菜单的末尾处,而 InsertMenu是在指定的位置处插入菜单项,
并将后面的菜单项依次下移。它们的函数原型如下:
返回 21
BOOL AppendMenu(UNIT nFlags,UNIT
nIDNewItem,const CBitmap * pBmp);
BOOL AppendMenu(UNIT nFlags,UNIT
nIDNewItem=0,LPCTSTR lpszNewItem=NULL);
BOOL InsertMenu(UNIT nPosition,UNIT nFlags,UNIT
nIDNewItem,const CBitmap *pBmp);
BOOL InsertMenu(UNIT nPosition,UNIT nFlags,UNIT
nIDNewItem=0,LPCTSTR lpszNewItem=NULL);
其中:形参 nIDNewItem表示新增菜单项的资源 ID号,
形参 lpszNewItem表示新增菜单项的标题内容,形参
pBmp是新增菜单项的位图指针,形参 nPosition表示新增菜单项要插入的菜单项的位置,nFlags表示要增加的菜单项的状态信息,其取值的不同会影响其他参数的含义,
见表 6.3。
返回 22
nFlags的取值 含义 nPosition值 nIDNewItem值 lpszNewItem值
MF_BYCOMMAND
MF_BYPOSITION
MF_POPUP
MF_SEPARATOR
MF_OWNERDRAW
MF_STRING
MF_CHECKED
MF_UNCHECKED
MF_DISABLED
MF_ENABLED
MF_GRAYED
菜单项以 ID
号来标识菜单项以位置来标识菜单项有弹出式子菜单分隔线自画菜单项字符串标志设置菜单项的选中标记取消菜单项的选中标记禁用菜单项菜单项可用菜单项变灰菜单项资源 ID
菜单项的位置弹出式菜单句柄忽略 忽略自画所需的数据字符串指针返回 23
注意:
( 1)当形参 nFlags为 MF_BYPOSITION时,nPosition表示新菜单项要插入的位置,该位置为 0时表示新菜单项插入到第一个菜单项,为 1时表示新菜单项插入到第二个菜单项,,当为 -1时,表示新菜单项插入到菜单的末尾
( 2)在形参 nFlags中,可以用按位或运算符,|” 将某些取值组合起来,如,MF_CHECKED|MF_STRING等。但有些组合是不允许的,如,MF_DISABLED、
MF_ENABLED和 MF_GRAYED等。
( 3)当利用以上函数向菜单中新增菜单后,不管菜单所在的窗口是否改变,都应调用 CWnd类的成员函数
CWnd::DrawMenuBar来更新菜单,函数 DrawMenuBar的原型为:
void DrawMenuBar();
返回 24
删除菜单项当要删除指定的菜单项时,可利用 CMenu类的成员函数 DeleteMenu来完成,该函数的原型为:
BOOL DeleteMenu(UNIT nPosition,UNIT nFlags);
其中:形参 nPosition的值表示要删除的菜单项的位置,
其值的选取要受到形参 nFlags的取值的影响。当 nFlags的取值为 MF_BYCOMMAND时,nPosition表示要删除的菜单项的 ID号,而当 nFlags的取值为 MF_BYPOSITION时,
nPosition表示要删除的菜单项的位置(第一个菜单项的位置为 0,第二个菜单项的位置为 1, )。
注意:
当调用 DeleteMenu函数删除某个菜单项后,不管菜单所依附的窗口是否改变,也必须调用 CWnd类的成员函数
CWnd::DrawMenuBar来更新菜单。
返回 25
获取菜单项可以利用 CMenu类的以下三个成员函数分别获得菜单的项数、菜单项的 ID号以及弹出式子菜单的句柄。
( 1) GetMenuItemCount函数该函数的原型为:
UNIT GetMenuItemCount() const;
该函数的功能是取得菜单中的菜单项数,如果调用失败则返回值为 -1。
( 2) GetMenuItemID函数该函数的原型是:
UNIT GetMenuItemID(int nPos) const;
该函数的功能是返回由参数 nPos所指定的菜单项位置的菜单项的 ID号,若 nPos所指定的位置处为分隔线,则该函数的返回值为 -1。
返回 26
( 3) GetSubMenu函数该函数的原型为:
CMenu *GetSubMenu(int nPos) const;
该函数的功能是获得指定菜单的弹出式菜单的菜单句柄。该弹出式菜单位置由参数 nPos给定,开始的位置为 0,
若菜单不存在,则创建一个临时的菜单指针。
此外,在主框架 CMainFrame类中,可以利用该类的成员函数 CMainFrame::GetMenu来获得主菜单句柄。该函数的原型为:
CMenu *GetMenu();
返回 27
5,快捷菜单的实现利用 MFC提供的 CMenu类的 TrackPopupMenu成员函数可以用来显示一个弹出式菜单,该函数的原型为:
BOOL TrackPopupMenu(UNIT nFlags,int x,int y,CWnd
*pWnd,LPCRECT lpRect=0);
其中:( 1)形参 nFlags表示菜单在屏幕上显示的位置以及鼠标的按钮状态,具体见表 6.4所示。其中前三个值可分别与后两个值用,|” 运算符进行组合。
nFlags的值 含义及作用
TPM_CENTERALIGN
TPM_LEFTALIGN
TPM_RIGHTALIGN
TPM_LEFTBUTTON
TPM_RIGHTBUTTON
决定菜单的屏幕位置,水平中心位置由 x坐标确定决定菜单的屏幕位置,菜单的左边位置由 x坐标确定决定菜单的屏幕位置,菜单的右边位置由 x坐标确定鼠标按钮标志,当用户单击左键时弹出快捷菜单鼠标按钮标志,当用户单击右键时弹出快捷菜单返回 28
( 2)形参 x和 y表示菜单的水平坐标和菜单的顶端的垂直坐标。
( 3) pWnd表示弹出菜单的窗口,此窗口将收到菜单全部的 WM_COMMAND消息。
( 4) lpRect是一个 RECT结构或 CRect类的对象指针,它表示一个矩形区域,用户单击这个区域时,弹出菜单不消失,而当 lpRect为 NULL时,则当用户单击菜单外面时,
菜单会立刻消失。
下面,我们在上例的基础上,添加一个快捷菜单,并使其能够完成与与双击应用程序窗口或选择 【 显示 】 菜单中的 【 个人资料 】 菜单项一样的功能。具体步骤如下:
步骤一,在 Visual C++ 6.0中,选择 【 File】 菜单中的
【 Open Workspace】 菜单项,打开上例中的,Dialog.dsw”
返回 29
步骤二,添加一个新的菜单资源 。 选择 【 Insert】 菜单中的 【 Resource】 菜单项,或直接按 Ctrl+R键,在打开的
【 Insert Resource】 对话框窗口中选择 【 Menu】,单击
【 New】 按钮 。
步骤三,在工作区窗口中选择 【 Resource View】 选项卡,
展开 【 Dialog Resources】 目录,再展开 【 Menu】 文件夹,
将会看到菜单 IDR_MENU1( 这是系统给该菜单资源的缺省 ID号 ) 。 双击 IDR_ MENU1,将在菜单资源编辑器中打开菜单资源 。 用鼠标双击主菜单最右边的空菜单项,
或者用鼠标右键单击它,在弹出的快捷菜单中选择
【 Properties】 菜单项 。 在出现的,Menu Item Properties”
对话框中的 【 Caption】 栏中任意输入一个标题,最后按回车键退出该对话框 。
返回 30
步骤四,在快捷菜单中增加菜单项 。 在菜单资源编辑器中用鼠标右键单击 【 显示 】 菜单中的空菜单项,在出现的快捷菜单中选择 【 Properties】 选项 。 在出现的,Menu
Item Properties” 属性对话框的 【 Caption】 栏中输入,个人资料 ( &D),,ID号输入,ID_MENU1_DATA”,按回车键关闭,Menu Item Properties” 对话框 。 以同样方法再增加一个 【 其他 】 菜单项,标题为,其他 ( &O),,
ID号为,__” 。
步骤五,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
将出现一对话框,询问是,创建一个新类 (Create a new
class)”,还是,选择一个已存在的类( Select an existing
class),,在此选择,选择一个已存在的类( Select an
existing class),,则系统又弹出,Select Class” 对话框,
在该对话框中,单击选择,CDialogView”,单击
【 Select】 按钮,系统进入 【 MFC ClassWizard】 对话框。
返回 31
步骤六,在 【 MFC ClassWizard】 对话框中,选择
【 Message Maps】 选项卡 。 在 【 Class name】 下拉列表框中,选择类 CDialogView ;在 【 Object Ids】 中选择
ID_MENU1_DATA 选项;在 【 Messages】 栏中选择
COMMAND。
步骤七,单击对话框右侧的 【 Add Function】 按钮,系统将会弹出 【 Add Member function】 对话框 。 系统将自动生成一个缺省名称为 OnMenu1Data的映射函数,在此保留此默认名称,单击 【 OK】 按钮继续 。
步骤八,单击 【 Edit Code】 按钮退出 【 MFC ClassWizard】
对话框,并 编 辑 新 增 加 的 函 数 OnMenu1Data 。 把
OnDisplayData()函数中的代码复制到 OnMenu1Data()中,
具体代码如下,其中粗体字为新添加的代码:
返回 32
void CDialogView::OnMenu1Data()
{
// TODO,Add your command handler code here
CMydataDialog dlg;
dlg.m_radio_m=0;
dlg.m_edit_name="";
CString msg;
if(dlg.DoModal()==IDOK)
{msg="<确定 >按钮被按下 ! ";}
else
{msg="<取消 >按钮被按下 ! "; }
返回 33
msg+="\r\n\n";
msg+="姓 名,";
msg+=dlg.m_edit_name;
msg+="\r\n";
msg+="性 别,";
switch(dlg.m_radio_m)
{case 0:msg+="男 ";
break;
case 1:msg+="女 ";
break;}
msg+="\r\n";
msg+="最高学历,";
msg+=dlg.m_combo_school;
msg+="\r\n";
msg+="爱 好,";
返回 34
if(dlg.m_check_art==TRUE)
msg+="艺术 ";
if(dlg.m_check_music==TRUE)
msg+="音乐 ";
if(dlg.m_check_sport==TRUE)
msg+="体育 ";
AfxMessageBox(msg);
}
步骤九,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
在出现的 【 MFC ClassWizard】 对话框中,选择
【 Message Maps】 选项卡 。 在 【 Class name】 下拉列表框中,选择 类 CMainFrame ;在 【 Object Ids】 中选择
CMainFrame 选项;在 【 Messages】 栏中选择
WM_CONTEXTMENU。 单击对话框右侧的 【 Add Function】
返回 35
按钮,系统将会弹出 【 Add Member function】 对话框 。
系统将自动生成一个缺省名称为 OnContextMenu的映射函数,单击 【 OK】 按钮 。 单击 【 Edit Code】 按钮退出
【 MFC ClassWizard】 对话框,并对 OnContextMenu函数进行如下编辑:
void CMainFrame::OnContextMenu(CWnd* pWnd,CPoint
point)
{// TODO,Add your message handler code here
CMenu menu;
menu.LoadMenu(IDR_MENU1);
menu.GetSubMenu(0)
->TrackPopupMenu(TPM_LEFTALIGN|TPM_
RIGHTBUTTON,point.x,point.y,this);
}
返回 36
步骤十:编译运行并测试此应用程序。当在应用程序窗口中,单击鼠标右键时,会弹出快捷菜单,选择其中的
【 个人资料 】 菜单项,则弹出 【 个人资料 】 对话框。在对话框内可以进行各种设置,然后单击 【 确认 】 或 【 取消 】 按钮退出。可以看到其效果与双击应用程序窗口或选择 【 显示 】 菜单中的 【 个人资料 】 菜单项是一样的。
6,动态向菜单中添加新的菜单项下面,我们在上例的基础上,向程序中动态增加一个新的菜单项,具体步骤如下:
步骤一,在 Visual C++ 6.0中,选择 【 File】 菜单中的
【 Open Workspace】 菜单项,打开上例中的 【 Dialog.dsw】
文件 。
步骤二,选择 【 View】 菜单中的 【 Resource Symbols】 菜单项,则会出现 【 Resource View】 对话框 。
返回 37
步骤三,单击对话框中 【 New? 】 按钮,则出现,New
Symbol” 对话框。在该对话框中的 Name文本框中,输入一个用于菜单项的 ID号,如:在本例中输入
,ID_NEW_MENUITEM” 。在 Value文本框中输入对在该 ID号的 ID值,系统缺省为 101,用户也可以自行修改成新值,新值必须处在 15~61440之间。在此取系统默认值,
单击 【 OK】 按钮。
步骤四,利用 Visual C++的工作区窗口,打开
CMainFrame类的实现文件 MainFrm.cpp文件,在
CMainFrame::OnCreate函数体中添加如下代码:
int CMainFrame::OnCreate(LPCREATESTRUCT
lpCreateStruct)
{// 前一部分在此省略返回 38
CMenu *pMainMenu=GetMenu();
CMenu *pSubMenu=pMainMenu->GetSubMenu (4);
CString StrOfNewMenuItem("新建菜单项 ");
pSubMenu->AppendMenu (MF_SEPARATOR);
pSubMenu->AppendMenu
(MF_STRING,ID_NEW_MENUITEM,StrOfNewMenuItem);
m_bAutoMenuEnable=FALSE;
pMainMenu->EnableMenuItem
(ID_NEW_MENUITEM,MF_BYCOMMAND|MF_ENABLED);
DrawMenuBar();
return 0;
}
返回 39
步骤五,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
在出现的 【 MFC ClassWizard】 对话框中,选择 【 Message
Maps】 选项卡。在 【 Class name】 下拉列表框中,选择类
CMainFrame;在 【 Object Ids】 中选择 CMainFrame选项;在
【 Messages】 栏中选择 OnCommand。单击对话框右侧的
【 Edit Code】 按钮,系统将会进入 CMainFrame::OnCommand
编辑窗口,输入以下黑体部分代码:
BOOL CMainFrame::OnCommand(WPARAM wParam,LPARAM
lParam)
{// TODO,Add your specialized code here and/or call the base class
if (LOWORD(wParam)==ID_NEW_MENUITEM)
MessageBox("您选中了新的菜单项 ");
return CFrameWnd::OnCommand(wParam,lParam); }
此步中完成了对新增菜单项的消息映射功能。
步骤六,编译运行并测试此应用程序。
返回 40
6.2 创建工具栏工具栏是一系列工具按钮的组合,也是一种常用的命令输入方式 。 可以说,工具栏是菜单的一种快捷方式 。
1,创建工具栏的方法和步骤创建工具栏资源在这里,我们将对上一节的例子进行扩充,增加一个工具栏 。 当用鼠标选择工具栏上的某个按钮时,显示出
【 个人资料 】 对话框 。 具体步骤如下:
步骤一,打开上一节创建的 Dialog例子 。
步骤二,在工作区窗口中选择 【 Resource View】 选项卡,
展开 【 Dialog Resources】 文件夹,由于我们在用
AppWizard生成应用程序时,没有选择生成工具栏,因此在 【 Dialog Resources】 文件夹中,找不到 Toolbar文件夹 。
返回 41
步骤三,选择 【 Insert】 菜单中的 【 Resource】 菜单项,
在弹出菜单中选择 【 Insert】 菜单项 。 系统将弹出
【 Insert Resource】 对话框,在 对 话 框 中 选 择
【 Toolbar】,单击 【 New】 按钮 。
步骤四,系统将自动在 【 Dialog Resounrces】 文件夹中添加一个 【 Toolbar】 文件夹,同时在 【 Toolbar】 文件夹中添加了一个名为 IDR_TOOLBAR1的文件。屏幕上同时显示工具栏设计窗口。
步骤四,鼠标右键单击 【 Resource View】 中 【 Toolbar】
文件夹中的 IDR_TOOLBAR1项目。在弹出菜单中选择
【 Properties】 菜单项,系统将弹出工具栏属性对话框。
在属性对话框中的 【 ID】 框中,我们把 ID号修改为
IDR_MYTOOLBAR。
返回 42
步骤五,添加按钮和制作按钮图标 。 我们可以利用
【 Graphic】 和 【 Color】 工具栏上提供的设计工具,根据自己需要制作按钮图标 。 我们用字母 R作为按钮的图标 。
工具栏按钮的绘制是一个个分开进行的,在画完一个按钮后,该按钮的实际效果立刻显示出来。
在 【 Toolbar Button Properties】 工具栏按钮属性对话框中,各项的含义如表 6.5所示 。
项目 含义
ID
Width
Height
Prompt
用于输入或从下拉列表中选择工具栏按钮的 ID号用于输入工具栏按钮的宽度,单位是像素用于输入工具栏按钮的高度,单位是像素工具栏按钮文本返回 43
注,要使选择工具栏按钮的功能与选择菜单的功能一致时,应将工具栏按钮属性对象框中的 ID号设置为与某一菜单项的 ID号相同 。
值得一提的是,在创建工具栏按钮的过程中,可以进行有关的操作及方法:
( 1) 创建新的工具栏按钮在新建一个工具栏的过程中,在工具栏的右端会有一个空按钮,用鼠标单击该按钮,则该按钮的周围有虚的方框包围,同时在编辑区内显示出该按钮,用户可以在其中绘制图形 。
( 2) 移动工具栏中的按钮在编辑工具栏的过程中,可以根据用户的需要移动工具栏中的按钮,将某个按钮放置到所需要的位置上 。
返回 44
( 3) 复制工具栏中的按钮在工具栏编辑窗口内,选择待移动的工具栏按钮,在按下 Ctrl键的同时,将其拖动到所需要的位置 。
( 4) 删除工具栏中的按钮方法是用鼠标拖动该按钮到工具栏以外的位置 。
( 5) 在工具栏中的按钮间插入空格可以根据需要在某个按钮的左边,右边或两边插入一个空格分隔符,方法是:
① 如果某按钮左边没有任何空格,拖动该按钮向右移动并当按钮的右边界接触到右边按钮时,释放鼠标键,则可以此按钮的左边插入一个空格,反之,亦然 。
② 如果某按钮的左边已有空格而右边没有空格,拖动该按钮向左移动并当按钮的左边界接触到左边按钮时,释放鼠标键,则可在此按钮右边插入一个空格 。
返回 45
③ 如果某按钮的左右两边都有空格,拖动该按钮向右移动并接触到相邻按钮时,则此按钮左边的空格保留,按钮右边的空格消失。反之亦然。
实现工具栏编码实现工具栏 。 具体实现步骤如下:
步骤一,在工作区中窗口中选中 【 Class View】 选项卡,
用鼠标右键单击 【 CmainFrame】,在弹出的菜单中选择
【 Add Member Variable】 菜单项,系统将弹出 【 Add
Member Variable】 对话框 。
步骤二,在 【 Variable Type】 栏中输入类型名称 CToolBar,
在 【 Variable Name】 栏中输入变量名称 m_MyDataToolBar。
单击 【 OK】 按钮继续 。
此时,Visual C++将自动在主框架中的类定义文件
MainFrm.h中添加以下声名,CToolBar m_MyDataToolBar;
返回 46
步骤三,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
或者直接按 Ctrl+R键,弹出 【 MFC ClassWizard】 对话框 。
在 【 Class name】 列表框选择 CmainFrame类;在 【 Object
Ids】 列表框中选中 CMainFrame;双击 【 Messages】 列表栏中的 WM_CREATE选项,或者选中 WM_CREATE,再单击 【 Add Function】 按钮 。 在 【 Member Function】 栏中将会出现 OnCreate()函数 。
步骤四,单击 【 Edit Code】 按钮,ClassWizard将自动在框 架 类 的 实 现 文 件 MainFrm.cpp 中 添 加 成 员 函 数
OnCreate()。 在函数中加入显示工具栏的代码 。 具体代码如下,其中粗体部分为新添加的代码 。
返回 47
Int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO,Add your specialized creation code here
if (!m_MyDataToolBar.Create(this)||
!m_MyDataToolBar.LoadToolBar(IDR_MYTOOLBAR))
{ TRACE0("Failed to created toolbar\n");
return -1;
}
return 0;
}
返回 48
步骤五,编译并运行该程序 。
当单击工具栏上的新建按钮,窗口中将弹出 【 个人资料 】 对话框 。 此按钮的作用和选择 【 显示 】 菜单中的
【 个人资料 】 菜单项的效果是一样的 。
说明:
( 1) 在上例创建工具栏的过程中,曾用到了 CToolBar类的对象,CToolBar类是由 CControlBar类派生而来的,它用于描述工具栏 。 其中,Create函数是其成员函数,该函数的原型为:
BOOL Create(Cwnd *pParentWnd,
DWORD wStyle=WS_CHILD|WS_VISIBLE|CBRS_TOP,
UNIT nID=AFX_IDW_TOOLBAR);
其中:参数 pParentWnd是指向父窗口的指针,dwStyle是工具栏的风格,nID是子窗口的 ID号 。
返回 49
取值 风格
CBRS_TOP
CBRS_BOTTOM
CBRS_NOALIGN
CBRS_TOOLTIPS
CBRS_SIZE_DYNAMIC
CBRS_SIZE_FIXED
CBRS_FLOATING
CBRS_FLYBY
CBRS_HIDE_INPLACE
在框架窗口的顶部在框架窗口的底部不随父窗口改变尺寸显示按钮提示尺寸可改变控件条固定浮动状态状态栏中显示按钮的信息不显示工具栏表 6.6 工具栏的部分风格返回 50
( 2) TRACE宏
TRACE宏提供了类似与 printf函数的输出格式,用于将某一信息 ( 即字符串 ) 输出到 Dump的设备环境 DC中 。 该宏只在调试状态下工作 。 TRACE宏的限制是一次最多输出 512个字符 。 如:
int i = 1;
char sz[] = "one";
TRACE( "Integer = %d,String = %s\n",i,sz );
此外,还有 TRACE0~TRACE3这样 4个独立的宏,分别用于输出纯字符串 ~字符串 +3个参数 。 它们的原型分别为:
TRACE0( exp )
TRACE1( exp,param1 )
TRACE2( exp,param1,param2 )
TRACE3( exp,param1,param2,param3 )
返回 51
如:
TRACE0( "Start Dump of MyClass members:" );
int i = 1;
TRACE1( "Integer = %d\n",i ); // Output,'Integer = 1'
int j = 1;
char sz[] = "one";
TRACE2( "Integer = %d,String = %s\n",j,sz ); // Output:
'Integer = 1,String = one'
2,如何实现工具栏的船坞化所谓 船坞化工具栏 就是可以将工具栏拖动到屏幕的任意位置上,还可以用鼠标改变工具栏的大小 。 下面我们就来实现工具栏的船坞化 。
返回 52
首 先 要 通 过 调 用 CControlBar 的 成 员 函 数
EnableDocking()使工具栏能够船坞化;然后通过调用
CFrameWnd类的成员函数 EnableDocking( ) 确保边框窗口 能 够 船 坞 化 ; 最 后 调 用 CFrameWnd 的 成 员 函 数
DockControlBar( ) 使工具栏固定在边框窗口上 。
所有这些工作都在边框窗口类的成员函数 OnCreate()中完成 。 这三个函数的原型为:
void CControlBar::EnableDocking( DWORD dwStyle );
void CFrameWnd::EnableDocking( DWORD dwDockStyle );
void CFrameWnd::DockControlBar( CControlBar * pBar,
UINT nDockBarID = 0,LPCRECT lpRect = NULL );
其中:参数 dwStyle和 dwDockStyle表示工具栏的风格,其取值见表 6.6,pBar是指向待船坞化的工具栏的指针 。
返回 53
具体代码如下,其中粗体部分为新添加的代码 。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO,Add your specialized creation code here
if (!m_MyDataToolBar.Create(this)||
!m_MyDataToolBar.LoadToolBar(IDR_MYTOOLBAR))
{ TRACE0("Failed to created toolbar\n");
return -1;
}
返回 54
m_MyDataToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_MyDataToolBar);
return 0;
}
编译并运行该应用程序,将看到工具栏已经船坞化了 。
可以用鼠标将它拖动到窗口的任意位置 。
返回 55
6.3 创建状态栏状态栏 位于应用程序框架窗口的底部,它可以分割成几个窗格,一般用于显示一些文本信息,比如:工具栏按钮的提示信息,Caps Lock键及 Num Lock键的状态等等 。
1,创建状态栏资源下面,我们在前例的基础上,为应用程序 Dialog添加一个状态栏,用来显示一个消息区,一个字符串和 Num Lock
键的状态 。 其具体步骤如下:
步骤一,为状态栏的内容建立一个 ID号 。
步骤二,在对话框中单击 【 New】 按钮,弹出 【 New
Symbol】 对 话 框,在 【 Name】 栏 中 填 入
ID_STATUSBAR_STR,在 【 Value】 栏中的数字是系统为用户提供的 ID数值 。 单击 【 OK】 按钮继续 。
返回 56
步骤三,新添加的 ID信息将会出现在 【 Resource Symbols】
对话框的列表中 。 单击 【 Close】 按钮关闭 【 Resource
Symbols】 对话框 。 此时完成创建 ID的工作 。 步骤四,在工作区窗口中选择 【 Resource View】 选项卡,双击
【 String Table】 文件夹中的 【 String Table】 选项,窗口中将显示出串表编辑器 。 在编辑器中单击鼠标右键,在弹出的菜单中选择 【 New String】 菜单项 。
步骤五,系统弹出 【 String Properties】 对话框,在 【 ID】
框中选择 ID_STATUSBAR_STR项,在 【 Caption】 框中输入字符串,测试状态栏!,,按 【 Enter】 键确认。
返回 57
2,实现状态栏实现状态栏的具体步骤如下:
步骤一,在工作区窗口中选择 【 Class View】 选项卡,用鼠标右键单击 【 CMainFrame】 选项,在弹出菜单中选择
【 Add Member Variable】 菜单项 。 弹出 【 Add Member
Variable】 对话框,在 【 Variable Type】 栏中输入类型名称
CStatusBar,在 【 Variable Name】 栏中输入类型名称为
m_MyStatusBar。 单击 【 OK】 按钮继续 。
此时,Visual C++ 将 自 动 在 主 框 架 的 类 定 义 文 件
MainFrm.h中添加以下声明:
CStatusBar m_MyStatusBar;
步骤二,在 MainFrm.cpp文件中加入数组 indicators的定义,
具体代码如下,其中粗体部分为新增加的代码 。
返回 58
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame,CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CONTEXTMENU()
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
static UINT indicators[]=
{ ID_SEPARATOR,//状态行指示器
ID_STATUSBAR_STR,
ID_INDICATOR_NUM,
};
返回 59
步骤三,在文件 MainFrm.app中对函数 OnCreate()进行修改,
增加状态栏的创建代码 。 具体代码如下,其中粗体部分为新增加的代码 。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{ if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO,Add your specialized creation code here
if (!m_MyDataToolBar.Create(this)||
!m_MyDataToolBar.LoadToolBar(IDR_MYTOOLBAR))
{ TRACE0("Failed to created toolbar\n");
return -1;
}
返回 60
m_MyDataToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_MyDataToolBar);
if(!m_MyStatusBar.Create(this)||
!m_MyStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{ TRACE0("Failed to created status bar \n");
return -1; //fail to create
}
return 0;
}
返回 61
步骤四,编译并运行此应用程序,将会看到在原来程序的基础之上,在窗口的最下端增加了一个状态栏。
说明:
( 1)在上例创建状态栏的过程中,曾用到了 CStatusBar类的对象,CStatusBar是 Visual C++的 MFC类库中的一个类,它用于描述状态栏,CStatusBar类是由 CControlBar类派生而来的。其中,Create函数是其成员函数,该函数的原型为:
BOOL Create( CWnd* pParentWnd,
DWORD dwStyle = WS_CHILD | WS_VISIBLE |CBRS_BOTTOM,
UINT nID = AFX_IDW_STATUS_BAR );
其中,pParentWnd是指向状态栏父窗口的指针,dwStyle是状态栏的风格,nID是子窗口的 ID号,表 6.7中列出了决定状态栏风格的几种常用的取值及对应的风格 。
返回 62
表 6.7 dwStyle的取值及对应的状态栏的风格
( 2) 在 MainFrm.cpp文件中加入的数组 indicators的定义:
static UINT indicators[],用于描述状态栏中所包含的内容。如果在利用 AppWizard向导创建 SDI或 MDI应用程序框架中的第 4步中,选择了,Initial status bar” 时,
则向导会自动在 MainFrm.cpp文件中加入数组 indicators
的定义。向导生成的缺省的 indicator数组包含了四个元素,它们是 ID_SEPARATOR,ID_INDICATOR_CAPS、
ID_INDICATOR_NUM和 ID_INDICATOR_SCRL。
取值 风格
CBRS_TOP
CBRS_BOTTOM
CBRS_NOALIGN
在框架窗口的顶部在框架窗口的底部当父窗口改变尺寸以后不随之变动返回 63
( 3) 要在状态栏的窗格中显示文本信息,可以采用以下三种方法:
① 调用 CWnd::SetWindowText函数更新信息行窗格中的文本 。 由于状态栏也是一种窗口,所以在程序中可以直接调用该函数 。 如:若状态栏变量为 m_wndStatusBar,则
m_wndStatusBar.SetWindowText(,新修改的信息,)语句将在信息行窗格中显示,新修改的信息,。
② 手动处理状态栏的 ON_UPDATE_COMMAND_UI更新信息,并在处理函数中调用 CCmdUI::SetText函数,该函数的原型为:
virtual void SetText( LPCTSTR lpszText );
其中:参数 lpszText是一个指向字符串的指针 。
返回 64
③ 调用函数 CStatusBar::SetPaneText 与
CStatusBar::GetPaneText可以设置或获得任何窗格 ( 包括信息行窗格 ) 中的文本 。 此函数的原型为:
BOOL SetPaneText( int nIndex,LPCTSTR lpszNewText,
BOOL bUpdate = TRUE );
CString GetPaneText( int nIndex ) const;
其中,参数 nIndex是待设置的窗格位置索引号 ( 第 1个窗格的位置索引为 0),lpszNewText表示要显示的字符串,
若参数 bUpdate的值为 TRUE,系统自动更新显示的结果 。
( 4) 调用 CStatusBar:,CommandToIndex 可以获得指定资源 ID号所在窗格的位置索引号,该函数的原型为:
int CommandToIndex( UINT nIDFind ) const;
其中:参数 nIDFind是状态栏中某一资源 ID号 。
返回 65
( 5 ) 调 用 函 数 CStatusBar::SetPaneInfo 与
CStatusBar::GetPaneInfo可设置或获得窗格的长度,风格等信息,它们的函数原型为:
void SetPaneInfo( int nIndex,UINT nID,UINT nStyle,int
cxWidth );
void GetPaneInfo( int nIndex,UINT& nID,UINT& nStyle,
int& cxWidth ) const;
其中:参数 nIndex表示要设置的状态栏窗格的索引号,
nID用来为状态栏窗格指定新的资源 ID号,cxWidth表示窗格的像素宽度,nStyle表示状态栏窗格的风格类型,用来指定窗格的外观,如,SBPS_POPOUT表示窗格是凸起来的 。 具体见表 6.8。
返回 66
风格取值 风格
SBPS_NOBORDERS
SBPS_POPOUT
SBPS_DISABLED
SBPS_STRETCH
SBPS_NOMAL
窗格四周没有 3D边框反显边框使文字凸起显示禁用窗格,不显示文本拉伸窗格,交填充窗格不用的空白空间 。 但状态栏中只能有一个窗格具有这种风格普通窗格,没有,拉伸,,,3D边框,,,文字凸起显示,等效果表 6.8 状态栏中各窗格的风格取值及对应风格返回 67
( 6 ) 调用 CStatusBar::SetPaneStyle 与
CStatusBar::GetPaneStyle可分别用来设置或获得状态栏窗格的风格,二者的原型如下:
UINT GetPaneStyle( int nIndex ) const;
void SetPaneStyle( int nIndex,UINT nStyle );
其中:参数 nIndex是状态栏中某一窗格的位置索引号,
nStyle为状态栏中窗格的风格 。
3,进一步完善状态栏现在,我们在刚才添加状态栏例子的基础上进行修改 。
当用户选择,关于,菜单项时,弹出,字体对话框,,
当单击,确定,按钮关闭此对话框后,在状态栏上原来显示文本测试状态栏的空格中显示,您已经查看过字体对话框 !”,按照下面的方法进行操作 。
返回 68
步骤一,选择 【 View】 菜单中的 【 ClassWizard】 菜单项 。
弹出 【 MFC ClassWizard】 对话框,在 【 Class name】 列表中选择类 CMainFrame,在 【 Object IDs】 列表中选择
ID_APP_ABOUT ;右边的 【 Messages】 栏中将出现
COMMAND 和 UPDATE_COMMAND_UI,双击
COMMAND选项 。 将弹出 Add Member Function 对话框 。
步骤二,接受系统缺省的函数名称 OnAppAbout,单击
【 OK】 按钮,返回 MFC ClassWizard对话框 。 这时在
MFC ClassWizard对话框中的 【 Member functions】 框中增加了一个函数 OnAppAbout。
步骤三,单击 【 Edit Code】 按钮,在代码编辑窗口中打开 OnAppAbout 函数 。 在编辑此函数之前,首先要在
MainFrm.cpp文件中添加一个 #include语句 。 具体代码如下,其中粗体部分为新增加的代码 。
返回 69
// MainFrm.cpp,implementation of the CMainFrame class
//
#include "stdafx.h"
#include "Dialog.h"
#include "MainFrm.h"
#include "MydataDialog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
返回 70
步骤四,在代码编辑窗口中,编辑函数 OnAppAbout()。 具体代码如下,其中粗体部分为新增加的代码 。
void CMainFrame::OnAppAbout()
{// TODO,Add your command handler code here
CMydataDialog dlg;
if(dlg.DoModal()==IDOK)
{
CClientDC dc(this);
SIZE size=dc.GetTextExtent("您已经查看过个人资料对话框 !");
int ndex=m_MyStatusBar.CommandToIndex(ID_STATUSBAR_STR);
m_MyStatusBar.SetPaneInfo(index,ID_STATUSBAR_STR,SBPS_POP
OUT,size.cx);
m_MyStatusBar.SetPaneText(index,_T("您已经查看过个人资料对话框 !"),TRUE);
}
}
返回 71
说明:
在此函数中,首先生成了一个字体对话框的实例,并且显示为有模式对话框 。 当用户单击 【 确定 】 按钮退出此对话框时,要改变状态栏的字符串显示 。
首先调用函数 GetTextExtent()来获得字符串的长度,然后调用 CommandToIndex()函数获得窗格的索引,再通过调用函数 SetPaneInfo()来设置窗格的长度,风格等信息 。 在此例中,我们使用了风格 SBPS_POPOUT,它使创建的窗格看起来是从状态栏中凸出来的 。
最后调用函数 SetPaneText()来显示文本内容 。
步骤五,编译并运行此应用程序。
返回 72
本章小结在应用程序中,要实现菜单的功能,其步骤和方法是先利用菜单编辑器建立菜单资源,然后编写菜单命令的
WM_COMMAND消息映射函数及相应代码 。 在 MFC框架中,菜单命令消息是按照一定的顺序进行传递的 。 对于一个单文档应用程序,消息传递的顺序为:视图类 → 文档类 → 框架类 → 应用程序类 。
Visual C++的 MFC提供的菜单类 Cmenu的对象可以用来表示各种 Windows菜单,其中包括顶层菜单项及其相应的弹出式菜单 。 并且利用该类的成员函数可以在程序运行时处理有关菜单的操作 。
工具栏是应用程序中常用操作的快捷方式,创建工具栏的方法是先创建工具栏资源,然后在主框架窗口类
CMainFrame中创建响应 WM_CREATE的消息映射函数,
在该函数中,利用 MFC提供的工具栏类 CToolBar对象的返回 73
Create 成 员 函 数,创 建 工 具 栏 。 CToolBar 类是由
CControlBar类派生而来的,它用于描述工具栏 。
状态栏中的空间按从左向右的顺序分为信息行窗格和指示器窗格,处在状态栏最左侧的窗格,其位置序号为 0,
向右依次类推,它可以分割成几个窗格,用来显示许多信息 。 其创建方法是先创建状态栏资源,然后在主框架窗口类 CMainFrame中创建响应 WM_CREATE的消息映射函数,在该函数中,利用 MFC 提 供 的 工 具 栏 类
CStatusBar 对象的 Create 成 员 函 数,创 建 状 态 栏 。
CStatusBar类是由 CControlBar类派生而来的,它用于描述状态栏 。 状态栏中的窗格的个数及所显示的信息由在
MainFrm.cpp文件中定义的数组 indicators的元素的个数和元素的值来决定 。
返回 74
习题
6.1 利用 AppWizard向导建立一个单文档应用程序,并完成以下操作:
( 1) 利用资源编辑器向原有菜单栏中增加一个顶层菜单
,查看,,并在其下拉菜单 ( 弹出菜单 ) 中添加,显示鼠标坐标,菜单项 。
( 2) 在主框架窗口类即 CMainFrame类中,建立响应
WM_COMMAND和 WM_COMMAND_UI消息映射函数,
函数名自定,函数的功能是,当程序运行过程中,用户选择,显示鼠标坐标,菜单项时能在该菜单项的左边显示,√” 标记,当再次选择该菜单项时标记消失 。
( 3) 为,显示鼠标坐标,菜单项建立一个快捷键
,Ctrl+D” 。
返回 75
( 4) 利用资源编辑器向现有的工具栏的末尾添加一个按钮,按钮的图标自己设计 。 并进行有关的设定使该按钮的功能同选择,显示鼠标坐标,菜单项的功能相同 。
( 5) 在现有状态栏的基础上再增加一个信息行窗格,用于显示鼠标移动过程中鼠标的当前 X,Y坐标 。
( 6) 利用 ClassWizard向导在应用程序的视图类中添加响应 WM_MOUSEMOVE消息的消息处理函数,函数名自定,
该函数的功能就是把鼠标在移动过程中的位置 X,Y坐标显示到状态栏的新增信息行窗格中 。
6.2 在 VC环境中,利用 Help菜单查看和学习 CMenu类,
CToolBar类,CStatusBar类,CCmdUI类的内容,即其中的数据成员和成员函数 。
第六章 菜单、工具栏和状态栏本章导读掌握菜单的创建步骤和方法,如何进行命令消息的映射和编写相应的程序代码 。
掌握 CMenu类及其常用成员函数的功能和使用方法,掌握利用这些成员函数创建快捷菜单和实现动态增加或减少菜单项 。
掌握工具栏的创建方法和步骤,如何将工具栏的功能与菜单的功能相对应 。
掌握创建状态栏的方法和步骤 。
学习和掌握 CMenu类,CStatusBar类,CToolBar类,
CCmdUI类及常用成员函数的功能和使用 。
菜单,工具栏和状态栏是 Windows应用程序中最重要的三个用户界面元素,是应用程序设计中不可缺少的步骤 。
返回 2
6.1 创建菜单菜单是一系列命令的列表,是最常用的命令输入方式 。
在 Windows中,几乎所有的命令操作都与菜单有关 。
Windows应用程序中的菜单是按照一定层次来进行组织的,包括菜单项和弹出菜单,其中弹出菜单又可以包括菜单项和其他的弹出菜单。
1.创建菜单资源菜单中的每一个菜单项都由 菜单项名 和 命令 ID号 两个基本要素组成 。 在菜单资源中,每个菜单项都必须有一个唯一的命令 ID号来对它进行标识,这个 ID号是系统在对菜单项进行识别时使用的 。 对于用户而言,菜单项的标识是利用它所属的弹出菜单和菜单项的句子来标识的,
比如 ID_FILE_OPEN,其所属的弹出菜单是 【 文件 】,菜单项名称为 【 打开 】 。
返回 3
创建菜单可以有几种方法,最简单的方法是用菜单资源编辑器进行设计 。 在这里,我们把第五章关于模式对话框的例子进行改造,使对话框的弹出方式由在窗口中双击鼠标改为由单击某个菜单命令实现 。 具体步骤如下:
步骤一,在 Visual C++ 6.0中,选 【 File】 菜单中的 【 Open
Workspace】 菜单项,打开已创建的,Dialog.dsw” 文件 。
步骤二,在工作区窗口中选择 【 Resource View】 选项卡,
展开 【 Dialog Resources】 目录,再展开 【 Menu】 文件,将会看到菜单 IDR_MAINFRAME。
步骤三,双击 IDR_MAINFRAME,将在菜单资源编辑器中打开菜单资源。
步骤四,在主菜单中增加一个 【 显示 】 菜单。用鼠标双击主菜单最右边的空菜单项,或者用鼠标右击,在弹出的快捷菜单中选择 【 Properties】 菜单项。系统将弹出属性对话框。
返回 4
在 【 Caption】 栏中输入,显示 ( &P),,括号中的 &P表示紧跟在它后面的字母,P” 是助记符,这样,在程序运行过程中,就可以用 Alt+P键来激活 【 显示 】 菜单 。 按
【 Enter】 键继续 。
这时,在主菜单中将增加一个,显示,菜单,在助记符
P下面有下划线 。 同时,在生成的菜单的右面和下面各出现一个新的菜单或菜单项,可以继续添加新的菜单或菜单项 。
步骤五,在 【 显示 】 菜单中增加一个 【 个人资料 】 菜单项 。 用鼠标右键单击 【 显示 】 菜单中的空菜单项,在弹出菜单中选择 【 Properties】 选项 。 单击属性对话框左上角的,图钉,按钮,把对话框,钉,在屏幕上 。 在属性对话框的 【 Caption】 栏中输入,个人资料 ( &D),。
返回 5
对于 【 个人资料 】 菜单项,Visual C++ 6.0将为该菜单项自动分配一个 ID号 。 单击其他菜单项或者屏幕的其他部分,再选中 【 个人资料 】 菜单项,系统在 【 ID】 栏中显示 出 为 该 菜 单 项 分 配 的 ID 号,其 一 般 格 式 为
MENUITEMxxxxx(xxxxx代表一个整数 )。 【 Prompt】 框中的文本是光标处于菜单项时,状态栏显示的帮助信息在菜单项属性对话框的 【 General】 选项卡中,各选项的含义如下图所示 。
步骤六,用鼠标左键按住 【 显示 】 菜单,将其拖到 【 编辑 】 与 【 帮助 】 菜单中间 。
这样,利用菜单资源编辑器,我们就很轻松地创建了一个标准的 Windows菜单。
返回 6
项目 含义
ID
Caption
Separator
Checked
Pop_up
Grayed
Inactive
Help
Break
Prompt
菜单的资源 ID号菜单项的标题文本,当其中某一字母的前面含有 &符号时,则该字母与 Alt键构成组合键选中时,则相应的菜单项是一个分隔符或一条水平线选中时,则相应的菜单项前显示一个选中标记,√,
选中时,表示该菜单项含有弹出式子菜单选中时,表示该菜单项呈灰色显示,该菜单项被禁用选中时,表示该菜单项没有被激活,用户不能选用选中时,表示该菜单项在程序运行时被放于顶层菜单的最右端其默认值为 None,表示菜单项按常规形式显示 。 该项的取值还可为 Column或 Bar,
指明当光标移到该菜单项时在状态栏上显示的提示表 6.1 菜单 General属性对话框的各项含义返回 7
2,建立快捷键在 Windows应用程序中的某些菜单项后面有一个组合键,
表示一个快捷键 ( shortcut key),在程序运行过程中,
如果用户按下了该组合键,则相应的菜单命令就会被执行 。 当然,若要使用快捷键选择某个菜单项,就必须事先对其作出定义 。 现在我们来为刚才创建的菜单添加快捷键,具体步骤如下:
步骤一,在工作区窗口的 【 Resource View】 选项卡中,
双击 【 Accelerator】 文件夹,双击 IDR_MAINFRAME,
则系统会弹出一个加速器表 。
步骤二,在加速器表中浏览一下,发现 Ctrl+D还没有被使用,我们就把 Ctrl+D设置为菜单项 【 个人资料 】 的快捷键 。
方法是双击加速器表末尾的空行,将弹出快捷键的属性对话框 ( Accel Properties) 。
返回 8
在属性对话框 ( Accel Properties) 中,各项的含义如表 6.2所示 。
表 6.2 Accel Properties对话框中各选项的含义选项 含义
ID
Modifiers
Type
Key
Next Key
Typed
为了能使设定的快捷键与某个菜单项的功能相对应,从中选择所需的菜单资源 ID号用来选择 Ctrl,Alt,Shift键是否为快捷键的组成键用来确定快捷键的值是虚拟键 (VirKey)还是 ASCII
是指启动快捷键的键盘按键单击此按钮时,用户所按的任何按键将成为快捷键的键值返回 9
步骤三,在对话框中的 【 ID】 下 拉 列 表 中 选 择
【 ID_DISPLAY_DATA】 选项,当选中 ID号时,【 ID】
框 中 同 时 显 示 出 此 ID 号 对 应 的 整 数,如
ID_DISPLAY_DATA=32771。
步骤四,在 【 Key】 列表框中输入,D”,确认
【 Modifiers】 栏中的 【 Ctrl】 复选框被选中,而且 【 Alt】
和 【 Shift】 都未被选中;或者,直接单击 【 Next Key
Typed】 按钮,按下 Ctrl+D组合键放开,此时系统会自动记录所按下的 Ctrl+D键为所要设定的组合键 。 按 【 Enter】
键继续 。
步骤五,为了在 【 显示 】 菜单中提示 【 个人资料 】 菜单项的快捷键,可以返回 6.1.1节中的步骤五,将 【 Caption】
框中的内容修改为,个人资料 (D)\tCtrl+D” 。
这样,我们就建立了一个完整的菜单资源 。
返回 10
3 菜单功能的实现在 MFC框架中,菜单命令消息是按照一定的 顺序 进行传递的 。 对于一个单文档应用程序,消息传递的顺序为:
视图类 → 文档类 → 框架类 → 应用程序类 。 因此,如果我们在视图类和文档类中同时定义了某个菜单项的消息映射接口时,由于消息首先传递给视图类,在视图类中对此消息做出了响应,所以,文档类中定义的此菜单项的消息映射函数就无法执行 。
在菜单资源中,我们定义了 MFC如何来构造菜单的结构,同 时 还 指 定 了 菜 单 的 资 源 ID 号,MFC 通过
ClassWizard会自动把菜单和相应的框架窗口联系在一起 。
但除了由系统产生的少量代码外,MFC不能自动地对程序的菜单项进行响应,必须用手工实现 。
返回 11
对于每个菜单项,系 统 提 供 了 COMMAND 和
UPDATE_COMMAND_UI两种消息可供选择:
( 1) COMMAND消息需要用户的干预,如单击,双击等操作;
( 2) UPDATE_COMMAND_UI消息系统会自动进行响应,
通过它可以实现对菜单项外观的动态管理 。 例如,设计人员可以使菜单有效,无效或给菜单项动态添加检查标记等 。
可以利用 ClassWizard同时设置这两种消息,但是在实际编程中,必须为每个菜单项提供有关 WM_COMMAND
类型消息映射接口 。
下面,我们在视图类中对前面已建立的,个人资料
( &D),菜单项的消息做出响应 。 具体步骤如下:
返回 12
步骤一,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
弹出 【 MFC ClassWizard】 对话框 。
步骤二,在 【 MFC ClassWizard】 对话框中,选择
【 Message Maps】 选项卡 。 在 【 Class name】 下拉列表框中,选择类 CDialogView;在 【 Object Ids】 中单击选择
ID_DISPLAY_DATA 选项;在 【 Messages】 栏中将出现
COMMAND和 UPDATE_COMMAND_UI两个选项,选中其中的 COMMAND。
步骤三,单击对话框右侧的 【 Add Function】 按钮,系统将会弹出 【 Add Member function】 对话框 。 系统将自动生成一个缺省名称为 OnDisplayData的映射函数亦可另取别的名称,在此取缺省名称,单击 【 OK】 按钮继续 。
步骤四,单击 【 Edit Code】 按钮退出 【 MFC ClassWizard】
对话框,并编辑新增加的函数 OnDisplayData。
返回 13
经过以上操作完成后,Visual C++会对程序中的一些程序文件的代码进行必要的修改,其中粗体部分的代码是由 ClassWizard自动添加的代码 。
1,在 CDialogView类的定义文件 DialogView.h中的消息映射部分将会改变为:
// Generated message map functions
protected:
//{{AFX_MSG(CDialogView)
afx_msg void OnLButtonDblClk(UINT nFlags,CPoint point);
afx_msg void OnDisplayData(); //ClassWizard自动添加的
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
返回 14
其中:
//{{AFX_MSG(CDialogView)
//}}AFX_MSG
是 ClassWizard分别用来识别命令消息处理函数定义的起始标记和结束标记,在 AFX_MSG(CDialogView)后面括号内的 CDialogView表示是处理该消息的类 。
2,在 CDialogView类的实现文件 DialogView.cpp中的消息映射部分也进行了一些修改:
BEGIN_MESSAGE_MAP(CDialogView,CView)
//{{AFX_MSG_MAP(CDialogView)
返回 15
ON_WM_LBUTTONDBLCLK()
ON_COMMAND(ID_DISPLAY_DATA,
OnDisplayData) //ClassWizard自动添加的
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
其中:
//{{AFX_MSG_MAP(CDialogView)
//}}AFX_MSG_MAP
是 ClassWizard标识命令消息处理映射机制的起始标记和结束标记 。
返回 16
3,在 DialogView.cpp文件中编写 OnDisplayData函数的代码 。
把 DialogView.cpp 文 件 中 响 应 双 击 窗 口 的 函 数
OnLButtonDBLCLK()的代码复制到 OnDisplayData()函数中,具体代码如下:
void CDialogView::OnDisplayData()
{// TODO,Add your command handler code here
CMydataDialog dlg;
dlg.m_radio_m=0;
dlg.m_edit_name="";
CString msg;
if(dlg.DoModal()==IDOK)
{msg="<确定 >按钮被按下 ! "; }
Else {msg="<取消 >按钮被按下 ! ";}
返回 17
msg+="\r\n";
msg+="姓名,";
msg+=dlg.m_edit_name;
msg+="\r\n";
msg+="性别,";
switch(dlg.m_radio_m)
{case 0:msg+="男 ";
break;
case 1:msg+="女 ";
break; }
msg+="\r\n";
msg+="最高学历,";
msg+=dlg.m_combo_school;
msg+="\r\n";
msg+="爱好,";
返回 18
if(dlg.m_check_art==TRUE)
msg+="艺术 ";
if(dlg.m_check_music==TRUE)
msg+="音乐 ";
if(dlg.m_check_sport==TRUE)
msg+="体育 ";
AfxMessageBox(msg);
}
步骤五,编译运行并测试此应用程序。当选择 【 显示 】
菜单中的 【 个人资料 】 菜单项,或单击 Ctrl+D键时,将弹出 【 个人资料 】 对话框,在对话框内可以进行各种设置,
然后单击 【 确认 】 或 【 取消 】 按钮退出。可以看到其效果与双击应用程序窗口是一样的。
返回 19
4,CMenu类及其常用成员函数介绍
Visual C++的 MFC提供的菜单类 Cmenu的对象可以用来表示各种 Windows菜单,其中包括顶层菜单项及其相应的弹出式菜单。并且该类可以在程序运行时处理有关菜单的操作,如创建菜单、装入菜单、删除菜单项、获取或设置菜单项的状态等。
创建菜单
CMenu类的成员函数 CreateMenu和 CreatePopupMenu分别用来创建一个菜单或子菜单框架,其函数原型如下:
BOOL CreateMenu(); //产生一个空菜单
BOOL CreatePopupMenu(); //产生一个空弹出式子菜单返回 20
装入菜单
CMenu类的成员函数 LoadMenu可用来将菜单资源装入应用程序中,它的函数原型有两种,如下所示:
BOOL LoadMenu(LPCTSTR lpszResourceName);
BOOL LoadMenu(UNIT nIDResource);
其中:形参 lpszResourceName表示菜单资源的名称,形参
nIDResource为菜单资源的 ID号。
添加菜单项当菜单创建后,可以调用 CMenu类提供的成员函数
AppendMenu或 InsertMenu来向菜单中添加一些菜单项,
但每次添加时,函数 AppendMenu是将菜单项添加在菜单的末尾处,而 InsertMenu是在指定的位置处插入菜单项,
并将后面的菜单项依次下移。它们的函数原型如下:
返回 21
BOOL AppendMenu(UNIT nFlags,UNIT
nIDNewItem,const CBitmap * pBmp);
BOOL AppendMenu(UNIT nFlags,UNIT
nIDNewItem=0,LPCTSTR lpszNewItem=NULL);
BOOL InsertMenu(UNIT nPosition,UNIT nFlags,UNIT
nIDNewItem,const CBitmap *pBmp);
BOOL InsertMenu(UNIT nPosition,UNIT nFlags,UNIT
nIDNewItem=0,LPCTSTR lpszNewItem=NULL);
其中:形参 nIDNewItem表示新增菜单项的资源 ID号,
形参 lpszNewItem表示新增菜单项的标题内容,形参
pBmp是新增菜单项的位图指针,形参 nPosition表示新增菜单项要插入的菜单项的位置,nFlags表示要增加的菜单项的状态信息,其取值的不同会影响其他参数的含义,
见表 6.3。
返回 22
nFlags的取值 含义 nPosition值 nIDNewItem值 lpszNewItem值
MF_BYCOMMAND
MF_BYPOSITION
MF_POPUP
MF_SEPARATOR
MF_OWNERDRAW
MF_STRING
MF_CHECKED
MF_UNCHECKED
MF_DISABLED
MF_ENABLED
MF_GRAYED
菜单项以 ID
号来标识菜单项以位置来标识菜单项有弹出式子菜单分隔线自画菜单项字符串标志设置菜单项的选中标记取消菜单项的选中标记禁用菜单项菜单项可用菜单项变灰菜单项资源 ID
菜单项的位置弹出式菜单句柄忽略 忽略自画所需的数据字符串指针返回 23
注意:
( 1)当形参 nFlags为 MF_BYPOSITION时,nPosition表示新菜单项要插入的位置,该位置为 0时表示新菜单项插入到第一个菜单项,为 1时表示新菜单项插入到第二个菜单项,,当为 -1时,表示新菜单项插入到菜单的末尾
( 2)在形参 nFlags中,可以用按位或运算符,|” 将某些取值组合起来,如,MF_CHECKED|MF_STRING等。但有些组合是不允许的,如,MF_DISABLED、
MF_ENABLED和 MF_GRAYED等。
( 3)当利用以上函数向菜单中新增菜单后,不管菜单所在的窗口是否改变,都应调用 CWnd类的成员函数
CWnd::DrawMenuBar来更新菜单,函数 DrawMenuBar的原型为:
void DrawMenuBar();
返回 24
删除菜单项当要删除指定的菜单项时,可利用 CMenu类的成员函数 DeleteMenu来完成,该函数的原型为:
BOOL DeleteMenu(UNIT nPosition,UNIT nFlags);
其中:形参 nPosition的值表示要删除的菜单项的位置,
其值的选取要受到形参 nFlags的取值的影响。当 nFlags的取值为 MF_BYCOMMAND时,nPosition表示要删除的菜单项的 ID号,而当 nFlags的取值为 MF_BYPOSITION时,
nPosition表示要删除的菜单项的位置(第一个菜单项的位置为 0,第二个菜单项的位置为 1, )。
注意:
当调用 DeleteMenu函数删除某个菜单项后,不管菜单所依附的窗口是否改变,也必须调用 CWnd类的成员函数
CWnd::DrawMenuBar来更新菜单。
返回 25
获取菜单项可以利用 CMenu类的以下三个成员函数分别获得菜单的项数、菜单项的 ID号以及弹出式子菜单的句柄。
( 1) GetMenuItemCount函数该函数的原型为:
UNIT GetMenuItemCount() const;
该函数的功能是取得菜单中的菜单项数,如果调用失败则返回值为 -1。
( 2) GetMenuItemID函数该函数的原型是:
UNIT GetMenuItemID(int nPos) const;
该函数的功能是返回由参数 nPos所指定的菜单项位置的菜单项的 ID号,若 nPos所指定的位置处为分隔线,则该函数的返回值为 -1。
返回 26
( 3) GetSubMenu函数该函数的原型为:
CMenu *GetSubMenu(int nPos) const;
该函数的功能是获得指定菜单的弹出式菜单的菜单句柄。该弹出式菜单位置由参数 nPos给定,开始的位置为 0,
若菜单不存在,则创建一个临时的菜单指针。
此外,在主框架 CMainFrame类中,可以利用该类的成员函数 CMainFrame::GetMenu来获得主菜单句柄。该函数的原型为:
CMenu *GetMenu();
返回 27
5,快捷菜单的实现利用 MFC提供的 CMenu类的 TrackPopupMenu成员函数可以用来显示一个弹出式菜单,该函数的原型为:
BOOL TrackPopupMenu(UNIT nFlags,int x,int y,CWnd
*pWnd,LPCRECT lpRect=0);
其中:( 1)形参 nFlags表示菜单在屏幕上显示的位置以及鼠标的按钮状态,具体见表 6.4所示。其中前三个值可分别与后两个值用,|” 运算符进行组合。
nFlags的值 含义及作用
TPM_CENTERALIGN
TPM_LEFTALIGN
TPM_RIGHTALIGN
TPM_LEFTBUTTON
TPM_RIGHTBUTTON
决定菜单的屏幕位置,水平中心位置由 x坐标确定决定菜单的屏幕位置,菜单的左边位置由 x坐标确定决定菜单的屏幕位置,菜单的右边位置由 x坐标确定鼠标按钮标志,当用户单击左键时弹出快捷菜单鼠标按钮标志,当用户单击右键时弹出快捷菜单返回 28
( 2)形参 x和 y表示菜单的水平坐标和菜单的顶端的垂直坐标。
( 3) pWnd表示弹出菜单的窗口,此窗口将收到菜单全部的 WM_COMMAND消息。
( 4) lpRect是一个 RECT结构或 CRect类的对象指针,它表示一个矩形区域,用户单击这个区域时,弹出菜单不消失,而当 lpRect为 NULL时,则当用户单击菜单外面时,
菜单会立刻消失。
下面,我们在上例的基础上,添加一个快捷菜单,并使其能够完成与与双击应用程序窗口或选择 【 显示 】 菜单中的 【 个人资料 】 菜单项一样的功能。具体步骤如下:
步骤一,在 Visual C++ 6.0中,选择 【 File】 菜单中的
【 Open Workspace】 菜单项,打开上例中的,Dialog.dsw”
返回 29
步骤二,添加一个新的菜单资源 。 选择 【 Insert】 菜单中的 【 Resource】 菜单项,或直接按 Ctrl+R键,在打开的
【 Insert Resource】 对话框窗口中选择 【 Menu】,单击
【 New】 按钮 。
步骤三,在工作区窗口中选择 【 Resource View】 选项卡,
展开 【 Dialog Resources】 目录,再展开 【 Menu】 文件夹,
将会看到菜单 IDR_MENU1( 这是系统给该菜单资源的缺省 ID号 ) 。 双击 IDR_ MENU1,将在菜单资源编辑器中打开菜单资源 。 用鼠标双击主菜单最右边的空菜单项,
或者用鼠标右键单击它,在弹出的快捷菜单中选择
【 Properties】 菜单项 。 在出现的,Menu Item Properties”
对话框中的 【 Caption】 栏中任意输入一个标题,最后按回车键退出该对话框 。
返回 30
步骤四,在快捷菜单中增加菜单项 。 在菜单资源编辑器中用鼠标右键单击 【 显示 】 菜单中的空菜单项,在出现的快捷菜单中选择 【 Properties】 选项 。 在出现的,Menu
Item Properties” 属性对话框的 【 Caption】 栏中输入,个人资料 ( &D),,ID号输入,ID_MENU1_DATA”,按回车键关闭,Menu Item Properties” 对话框 。 以同样方法再增加一个 【 其他 】 菜单项,标题为,其他 ( &O),,
ID号为,__” 。
步骤五,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
将出现一对话框,询问是,创建一个新类 (Create a new
class)”,还是,选择一个已存在的类( Select an existing
class),,在此选择,选择一个已存在的类( Select an
existing class),,则系统又弹出,Select Class” 对话框,
在该对话框中,单击选择,CDialogView”,单击
【 Select】 按钮,系统进入 【 MFC ClassWizard】 对话框。
返回 31
步骤六,在 【 MFC ClassWizard】 对话框中,选择
【 Message Maps】 选项卡 。 在 【 Class name】 下拉列表框中,选择类 CDialogView ;在 【 Object Ids】 中选择
ID_MENU1_DATA 选项;在 【 Messages】 栏中选择
COMMAND。
步骤七,单击对话框右侧的 【 Add Function】 按钮,系统将会弹出 【 Add Member function】 对话框 。 系统将自动生成一个缺省名称为 OnMenu1Data的映射函数,在此保留此默认名称,单击 【 OK】 按钮继续 。
步骤八,单击 【 Edit Code】 按钮退出 【 MFC ClassWizard】
对话框,并 编 辑 新 增 加 的 函 数 OnMenu1Data 。 把
OnDisplayData()函数中的代码复制到 OnMenu1Data()中,
具体代码如下,其中粗体字为新添加的代码:
返回 32
void CDialogView::OnMenu1Data()
{
// TODO,Add your command handler code here
CMydataDialog dlg;
dlg.m_radio_m=0;
dlg.m_edit_name="";
CString msg;
if(dlg.DoModal()==IDOK)
{msg="<确定 >按钮被按下 ! ";}
else
{msg="<取消 >按钮被按下 ! "; }
返回 33
msg+="\r\n\n";
msg+="姓 名,";
msg+=dlg.m_edit_name;
msg+="\r\n";
msg+="性 别,";
switch(dlg.m_radio_m)
{case 0:msg+="男 ";
break;
case 1:msg+="女 ";
break;}
msg+="\r\n";
msg+="最高学历,";
msg+=dlg.m_combo_school;
msg+="\r\n";
msg+="爱 好,";
返回 34
if(dlg.m_check_art==TRUE)
msg+="艺术 ";
if(dlg.m_check_music==TRUE)
msg+="音乐 ";
if(dlg.m_check_sport==TRUE)
msg+="体育 ";
AfxMessageBox(msg);
}
步骤九,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
在出现的 【 MFC ClassWizard】 对话框中,选择
【 Message Maps】 选项卡 。 在 【 Class name】 下拉列表框中,选择 类 CMainFrame ;在 【 Object Ids】 中选择
CMainFrame 选项;在 【 Messages】 栏中选择
WM_CONTEXTMENU。 单击对话框右侧的 【 Add Function】
返回 35
按钮,系统将会弹出 【 Add Member function】 对话框 。
系统将自动生成一个缺省名称为 OnContextMenu的映射函数,单击 【 OK】 按钮 。 单击 【 Edit Code】 按钮退出
【 MFC ClassWizard】 对话框,并对 OnContextMenu函数进行如下编辑:
void CMainFrame::OnContextMenu(CWnd* pWnd,CPoint
point)
{// TODO,Add your message handler code here
CMenu menu;
menu.LoadMenu(IDR_MENU1);
menu.GetSubMenu(0)
->TrackPopupMenu(TPM_LEFTALIGN|TPM_
RIGHTBUTTON,point.x,point.y,this);
}
返回 36
步骤十:编译运行并测试此应用程序。当在应用程序窗口中,单击鼠标右键时,会弹出快捷菜单,选择其中的
【 个人资料 】 菜单项,则弹出 【 个人资料 】 对话框。在对话框内可以进行各种设置,然后单击 【 确认 】 或 【 取消 】 按钮退出。可以看到其效果与双击应用程序窗口或选择 【 显示 】 菜单中的 【 个人资料 】 菜单项是一样的。
6,动态向菜单中添加新的菜单项下面,我们在上例的基础上,向程序中动态增加一个新的菜单项,具体步骤如下:
步骤一,在 Visual C++ 6.0中,选择 【 File】 菜单中的
【 Open Workspace】 菜单项,打开上例中的 【 Dialog.dsw】
文件 。
步骤二,选择 【 View】 菜单中的 【 Resource Symbols】 菜单项,则会出现 【 Resource View】 对话框 。
返回 37
步骤三,单击对话框中 【 New? 】 按钮,则出现,New
Symbol” 对话框。在该对话框中的 Name文本框中,输入一个用于菜单项的 ID号,如:在本例中输入
,ID_NEW_MENUITEM” 。在 Value文本框中输入对在该 ID号的 ID值,系统缺省为 101,用户也可以自行修改成新值,新值必须处在 15~61440之间。在此取系统默认值,
单击 【 OK】 按钮。
步骤四,利用 Visual C++的工作区窗口,打开
CMainFrame类的实现文件 MainFrm.cpp文件,在
CMainFrame::OnCreate函数体中添加如下代码:
int CMainFrame::OnCreate(LPCREATESTRUCT
lpCreateStruct)
{// 前一部分在此省略返回 38
CMenu *pMainMenu=GetMenu();
CMenu *pSubMenu=pMainMenu->GetSubMenu (4);
CString StrOfNewMenuItem("新建菜单项 ");
pSubMenu->AppendMenu (MF_SEPARATOR);
pSubMenu->AppendMenu
(MF_STRING,ID_NEW_MENUITEM,StrOfNewMenuItem);
m_bAutoMenuEnable=FALSE;
pMainMenu->EnableMenuItem
(ID_NEW_MENUITEM,MF_BYCOMMAND|MF_ENABLED);
DrawMenuBar();
return 0;
}
返回 39
步骤五,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
在出现的 【 MFC ClassWizard】 对话框中,选择 【 Message
Maps】 选项卡。在 【 Class name】 下拉列表框中,选择类
CMainFrame;在 【 Object Ids】 中选择 CMainFrame选项;在
【 Messages】 栏中选择 OnCommand。单击对话框右侧的
【 Edit Code】 按钮,系统将会进入 CMainFrame::OnCommand
编辑窗口,输入以下黑体部分代码:
BOOL CMainFrame::OnCommand(WPARAM wParam,LPARAM
lParam)
{// TODO,Add your specialized code here and/or call the base class
if (LOWORD(wParam)==ID_NEW_MENUITEM)
MessageBox("您选中了新的菜单项 ");
return CFrameWnd::OnCommand(wParam,lParam); }
此步中完成了对新增菜单项的消息映射功能。
步骤六,编译运行并测试此应用程序。
返回 40
6.2 创建工具栏工具栏是一系列工具按钮的组合,也是一种常用的命令输入方式 。 可以说,工具栏是菜单的一种快捷方式 。
1,创建工具栏的方法和步骤创建工具栏资源在这里,我们将对上一节的例子进行扩充,增加一个工具栏 。 当用鼠标选择工具栏上的某个按钮时,显示出
【 个人资料 】 对话框 。 具体步骤如下:
步骤一,打开上一节创建的 Dialog例子 。
步骤二,在工作区窗口中选择 【 Resource View】 选项卡,
展开 【 Dialog Resources】 文件夹,由于我们在用
AppWizard生成应用程序时,没有选择生成工具栏,因此在 【 Dialog Resources】 文件夹中,找不到 Toolbar文件夹 。
返回 41
步骤三,选择 【 Insert】 菜单中的 【 Resource】 菜单项,
在弹出菜单中选择 【 Insert】 菜单项 。 系统将弹出
【 Insert Resource】 对话框,在 对 话 框 中 选 择
【 Toolbar】,单击 【 New】 按钮 。
步骤四,系统将自动在 【 Dialog Resounrces】 文件夹中添加一个 【 Toolbar】 文件夹,同时在 【 Toolbar】 文件夹中添加了一个名为 IDR_TOOLBAR1的文件。屏幕上同时显示工具栏设计窗口。
步骤四,鼠标右键单击 【 Resource View】 中 【 Toolbar】
文件夹中的 IDR_TOOLBAR1项目。在弹出菜单中选择
【 Properties】 菜单项,系统将弹出工具栏属性对话框。
在属性对话框中的 【 ID】 框中,我们把 ID号修改为
IDR_MYTOOLBAR。
返回 42
步骤五,添加按钮和制作按钮图标 。 我们可以利用
【 Graphic】 和 【 Color】 工具栏上提供的设计工具,根据自己需要制作按钮图标 。 我们用字母 R作为按钮的图标 。
工具栏按钮的绘制是一个个分开进行的,在画完一个按钮后,该按钮的实际效果立刻显示出来。
在 【 Toolbar Button Properties】 工具栏按钮属性对话框中,各项的含义如表 6.5所示 。
项目 含义
ID
Width
Height
Prompt
用于输入或从下拉列表中选择工具栏按钮的 ID号用于输入工具栏按钮的宽度,单位是像素用于输入工具栏按钮的高度,单位是像素工具栏按钮文本返回 43
注,要使选择工具栏按钮的功能与选择菜单的功能一致时,应将工具栏按钮属性对象框中的 ID号设置为与某一菜单项的 ID号相同 。
值得一提的是,在创建工具栏按钮的过程中,可以进行有关的操作及方法:
( 1) 创建新的工具栏按钮在新建一个工具栏的过程中,在工具栏的右端会有一个空按钮,用鼠标单击该按钮,则该按钮的周围有虚的方框包围,同时在编辑区内显示出该按钮,用户可以在其中绘制图形 。
( 2) 移动工具栏中的按钮在编辑工具栏的过程中,可以根据用户的需要移动工具栏中的按钮,将某个按钮放置到所需要的位置上 。
返回 44
( 3) 复制工具栏中的按钮在工具栏编辑窗口内,选择待移动的工具栏按钮,在按下 Ctrl键的同时,将其拖动到所需要的位置 。
( 4) 删除工具栏中的按钮方法是用鼠标拖动该按钮到工具栏以外的位置 。
( 5) 在工具栏中的按钮间插入空格可以根据需要在某个按钮的左边,右边或两边插入一个空格分隔符,方法是:
① 如果某按钮左边没有任何空格,拖动该按钮向右移动并当按钮的右边界接触到右边按钮时,释放鼠标键,则可以此按钮的左边插入一个空格,反之,亦然 。
② 如果某按钮的左边已有空格而右边没有空格,拖动该按钮向左移动并当按钮的左边界接触到左边按钮时,释放鼠标键,则可在此按钮右边插入一个空格 。
返回 45
③ 如果某按钮的左右两边都有空格,拖动该按钮向右移动并接触到相邻按钮时,则此按钮左边的空格保留,按钮右边的空格消失。反之亦然。
实现工具栏编码实现工具栏 。 具体实现步骤如下:
步骤一,在工作区中窗口中选中 【 Class View】 选项卡,
用鼠标右键单击 【 CmainFrame】,在弹出的菜单中选择
【 Add Member Variable】 菜单项,系统将弹出 【 Add
Member Variable】 对话框 。
步骤二,在 【 Variable Type】 栏中输入类型名称 CToolBar,
在 【 Variable Name】 栏中输入变量名称 m_MyDataToolBar。
单击 【 OK】 按钮继续 。
此时,Visual C++将自动在主框架中的类定义文件
MainFrm.h中添加以下声名,CToolBar m_MyDataToolBar;
返回 46
步骤三,选择 【 View】 菜单中的 【 ClassWizard】 菜单项,
或者直接按 Ctrl+R键,弹出 【 MFC ClassWizard】 对话框 。
在 【 Class name】 列表框选择 CmainFrame类;在 【 Object
Ids】 列表框中选中 CMainFrame;双击 【 Messages】 列表栏中的 WM_CREATE选项,或者选中 WM_CREATE,再单击 【 Add Function】 按钮 。 在 【 Member Function】 栏中将会出现 OnCreate()函数 。
步骤四,单击 【 Edit Code】 按钮,ClassWizard将自动在框 架 类 的 实 现 文 件 MainFrm.cpp 中 添 加 成 员 函 数
OnCreate()。 在函数中加入显示工具栏的代码 。 具体代码如下,其中粗体部分为新添加的代码 。
返回 47
Int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO,Add your specialized creation code here
if (!m_MyDataToolBar.Create(this)||
!m_MyDataToolBar.LoadToolBar(IDR_MYTOOLBAR))
{ TRACE0("Failed to created toolbar\n");
return -1;
}
return 0;
}
返回 48
步骤五,编译并运行该程序 。
当单击工具栏上的新建按钮,窗口中将弹出 【 个人资料 】 对话框 。 此按钮的作用和选择 【 显示 】 菜单中的
【 个人资料 】 菜单项的效果是一样的 。
说明:
( 1) 在上例创建工具栏的过程中,曾用到了 CToolBar类的对象,CToolBar类是由 CControlBar类派生而来的,它用于描述工具栏 。 其中,Create函数是其成员函数,该函数的原型为:
BOOL Create(Cwnd *pParentWnd,
DWORD wStyle=WS_CHILD|WS_VISIBLE|CBRS_TOP,
UNIT nID=AFX_IDW_TOOLBAR);
其中:参数 pParentWnd是指向父窗口的指针,dwStyle是工具栏的风格,nID是子窗口的 ID号 。
返回 49
取值 风格
CBRS_TOP
CBRS_BOTTOM
CBRS_NOALIGN
CBRS_TOOLTIPS
CBRS_SIZE_DYNAMIC
CBRS_SIZE_FIXED
CBRS_FLOATING
CBRS_FLYBY
CBRS_HIDE_INPLACE
在框架窗口的顶部在框架窗口的底部不随父窗口改变尺寸显示按钮提示尺寸可改变控件条固定浮动状态状态栏中显示按钮的信息不显示工具栏表 6.6 工具栏的部分风格返回 50
( 2) TRACE宏
TRACE宏提供了类似与 printf函数的输出格式,用于将某一信息 ( 即字符串 ) 输出到 Dump的设备环境 DC中 。 该宏只在调试状态下工作 。 TRACE宏的限制是一次最多输出 512个字符 。 如:
int i = 1;
char sz[] = "one";
TRACE( "Integer = %d,String = %s\n",i,sz );
此外,还有 TRACE0~TRACE3这样 4个独立的宏,分别用于输出纯字符串 ~字符串 +3个参数 。 它们的原型分别为:
TRACE0( exp )
TRACE1( exp,param1 )
TRACE2( exp,param1,param2 )
TRACE3( exp,param1,param2,param3 )
返回 51
如:
TRACE0( "Start Dump of MyClass members:" );
int i = 1;
TRACE1( "Integer = %d\n",i ); // Output,'Integer = 1'
int j = 1;
char sz[] = "one";
TRACE2( "Integer = %d,String = %s\n",j,sz ); // Output:
'Integer = 1,String = one'
2,如何实现工具栏的船坞化所谓 船坞化工具栏 就是可以将工具栏拖动到屏幕的任意位置上,还可以用鼠标改变工具栏的大小 。 下面我们就来实现工具栏的船坞化 。
返回 52
首 先 要 通 过 调 用 CControlBar 的 成 员 函 数
EnableDocking()使工具栏能够船坞化;然后通过调用
CFrameWnd类的成员函数 EnableDocking( ) 确保边框窗口 能 够 船 坞 化 ; 最 后 调 用 CFrameWnd 的 成 员 函 数
DockControlBar( ) 使工具栏固定在边框窗口上 。
所有这些工作都在边框窗口类的成员函数 OnCreate()中完成 。 这三个函数的原型为:
void CControlBar::EnableDocking( DWORD dwStyle );
void CFrameWnd::EnableDocking( DWORD dwDockStyle );
void CFrameWnd::DockControlBar( CControlBar * pBar,
UINT nDockBarID = 0,LPCRECT lpRect = NULL );
其中:参数 dwStyle和 dwDockStyle表示工具栏的风格,其取值见表 6.6,pBar是指向待船坞化的工具栏的指针 。
返回 53
具体代码如下,其中粗体部分为新添加的代码 。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO,Add your specialized creation code here
if (!m_MyDataToolBar.Create(this)||
!m_MyDataToolBar.LoadToolBar(IDR_MYTOOLBAR))
{ TRACE0("Failed to created toolbar\n");
return -1;
}
返回 54
m_MyDataToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_MyDataToolBar);
return 0;
}
编译并运行该应用程序,将看到工具栏已经船坞化了 。
可以用鼠标将它拖动到窗口的任意位置 。
返回 55
6.3 创建状态栏状态栏 位于应用程序框架窗口的底部,它可以分割成几个窗格,一般用于显示一些文本信息,比如:工具栏按钮的提示信息,Caps Lock键及 Num Lock键的状态等等 。
1,创建状态栏资源下面,我们在前例的基础上,为应用程序 Dialog添加一个状态栏,用来显示一个消息区,一个字符串和 Num Lock
键的状态 。 其具体步骤如下:
步骤一,为状态栏的内容建立一个 ID号 。
步骤二,在对话框中单击 【 New】 按钮,弹出 【 New
Symbol】 对 话 框,在 【 Name】 栏 中 填 入
ID_STATUSBAR_STR,在 【 Value】 栏中的数字是系统为用户提供的 ID数值 。 单击 【 OK】 按钮继续 。
返回 56
步骤三,新添加的 ID信息将会出现在 【 Resource Symbols】
对话框的列表中 。 单击 【 Close】 按钮关闭 【 Resource
Symbols】 对话框 。 此时完成创建 ID的工作 。 步骤四,在工作区窗口中选择 【 Resource View】 选项卡,双击
【 String Table】 文件夹中的 【 String Table】 选项,窗口中将显示出串表编辑器 。 在编辑器中单击鼠标右键,在弹出的菜单中选择 【 New String】 菜单项 。
步骤五,系统弹出 【 String Properties】 对话框,在 【 ID】
框中选择 ID_STATUSBAR_STR项,在 【 Caption】 框中输入字符串,测试状态栏!,,按 【 Enter】 键确认。
返回 57
2,实现状态栏实现状态栏的具体步骤如下:
步骤一,在工作区窗口中选择 【 Class View】 选项卡,用鼠标右键单击 【 CMainFrame】 选项,在弹出菜单中选择
【 Add Member Variable】 菜单项 。 弹出 【 Add Member
Variable】 对话框,在 【 Variable Type】 栏中输入类型名称
CStatusBar,在 【 Variable Name】 栏中输入类型名称为
m_MyStatusBar。 单击 【 OK】 按钮继续 。
此时,Visual C++ 将 自 动 在 主 框 架 的 类 定 义 文 件
MainFrm.h中添加以下声明:
CStatusBar m_MyStatusBar;
步骤二,在 MainFrm.cpp文件中加入数组 indicators的定义,
具体代码如下,其中粗体部分为新增加的代码 。
返回 58
// CMainFrame
IMPLEMENT_DYNCREATE(CMainFrame,CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CONTEXTMENU()
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
static UINT indicators[]=
{ ID_SEPARATOR,//状态行指示器
ID_STATUSBAR_STR,
ID_INDICATOR_NUM,
};
返回 59
步骤三,在文件 MainFrm.app中对函数 OnCreate()进行修改,
增加状态栏的创建代码 。 具体代码如下,其中粗体部分为新增加的代码 。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{ if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO,Add your specialized creation code here
if (!m_MyDataToolBar.Create(this)||
!m_MyDataToolBar.LoadToolBar(IDR_MYTOOLBAR))
{ TRACE0("Failed to created toolbar\n");
return -1;
}
返回 60
m_MyDataToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_MyDataToolBar);
if(!m_MyStatusBar.Create(this)||
!m_MyStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{ TRACE0("Failed to created status bar \n");
return -1; //fail to create
}
return 0;
}
返回 61
步骤四,编译并运行此应用程序,将会看到在原来程序的基础之上,在窗口的最下端增加了一个状态栏。
说明:
( 1)在上例创建状态栏的过程中,曾用到了 CStatusBar类的对象,CStatusBar是 Visual C++的 MFC类库中的一个类,它用于描述状态栏,CStatusBar类是由 CControlBar类派生而来的。其中,Create函数是其成员函数,该函数的原型为:
BOOL Create( CWnd* pParentWnd,
DWORD dwStyle = WS_CHILD | WS_VISIBLE |CBRS_BOTTOM,
UINT nID = AFX_IDW_STATUS_BAR );
其中,pParentWnd是指向状态栏父窗口的指针,dwStyle是状态栏的风格,nID是子窗口的 ID号,表 6.7中列出了决定状态栏风格的几种常用的取值及对应的风格 。
返回 62
表 6.7 dwStyle的取值及对应的状态栏的风格
( 2) 在 MainFrm.cpp文件中加入的数组 indicators的定义:
static UINT indicators[],用于描述状态栏中所包含的内容。如果在利用 AppWizard向导创建 SDI或 MDI应用程序框架中的第 4步中,选择了,Initial status bar” 时,
则向导会自动在 MainFrm.cpp文件中加入数组 indicators
的定义。向导生成的缺省的 indicator数组包含了四个元素,它们是 ID_SEPARATOR,ID_INDICATOR_CAPS、
ID_INDICATOR_NUM和 ID_INDICATOR_SCRL。
取值 风格
CBRS_TOP
CBRS_BOTTOM
CBRS_NOALIGN
在框架窗口的顶部在框架窗口的底部当父窗口改变尺寸以后不随之变动返回 63
( 3) 要在状态栏的窗格中显示文本信息,可以采用以下三种方法:
① 调用 CWnd::SetWindowText函数更新信息行窗格中的文本 。 由于状态栏也是一种窗口,所以在程序中可以直接调用该函数 。 如:若状态栏变量为 m_wndStatusBar,则
m_wndStatusBar.SetWindowText(,新修改的信息,)语句将在信息行窗格中显示,新修改的信息,。
② 手动处理状态栏的 ON_UPDATE_COMMAND_UI更新信息,并在处理函数中调用 CCmdUI::SetText函数,该函数的原型为:
virtual void SetText( LPCTSTR lpszText );
其中:参数 lpszText是一个指向字符串的指针 。
返回 64
③ 调用函数 CStatusBar::SetPaneText 与
CStatusBar::GetPaneText可以设置或获得任何窗格 ( 包括信息行窗格 ) 中的文本 。 此函数的原型为:
BOOL SetPaneText( int nIndex,LPCTSTR lpszNewText,
BOOL bUpdate = TRUE );
CString GetPaneText( int nIndex ) const;
其中,参数 nIndex是待设置的窗格位置索引号 ( 第 1个窗格的位置索引为 0),lpszNewText表示要显示的字符串,
若参数 bUpdate的值为 TRUE,系统自动更新显示的结果 。
( 4) 调用 CStatusBar:,CommandToIndex 可以获得指定资源 ID号所在窗格的位置索引号,该函数的原型为:
int CommandToIndex( UINT nIDFind ) const;
其中:参数 nIDFind是状态栏中某一资源 ID号 。
返回 65
( 5 ) 调 用 函 数 CStatusBar::SetPaneInfo 与
CStatusBar::GetPaneInfo可设置或获得窗格的长度,风格等信息,它们的函数原型为:
void SetPaneInfo( int nIndex,UINT nID,UINT nStyle,int
cxWidth );
void GetPaneInfo( int nIndex,UINT& nID,UINT& nStyle,
int& cxWidth ) const;
其中:参数 nIndex表示要设置的状态栏窗格的索引号,
nID用来为状态栏窗格指定新的资源 ID号,cxWidth表示窗格的像素宽度,nStyle表示状态栏窗格的风格类型,用来指定窗格的外观,如,SBPS_POPOUT表示窗格是凸起来的 。 具体见表 6.8。
返回 66
风格取值 风格
SBPS_NOBORDERS
SBPS_POPOUT
SBPS_DISABLED
SBPS_STRETCH
SBPS_NOMAL
窗格四周没有 3D边框反显边框使文字凸起显示禁用窗格,不显示文本拉伸窗格,交填充窗格不用的空白空间 。 但状态栏中只能有一个窗格具有这种风格普通窗格,没有,拉伸,,,3D边框,,,文字凸起显示,等效果表 6.8 状态栏中各窗格的风格取值及对应风格返回 67
( 6 ) 调用 CStatusBar::SetPaneStyle 与
CStatusBar::GetPaneStyle可分别用来设置或获得状态栏窗格的风格,二者的原型如下:
UINT GetPaneStyle( int nIndex ) const;
void SetPaneStyle( int nIndex,UINT nStyle );
其中:参数 nIndex是状态栏中某一窗格的位置索引号,
nStyle为状态栏中窗格的风格 。
3,进一步完善状态栏现在,我们在刚才添加状态栏例子的基础上进行修改 。
当用户选择,关于,菜单项时,弹出,字体对话框,,
当单击,确定,按钮关闭此对话框后,在状态栏上原来显示文本测试状态栏的空格中显示,您已经查看过字体对话框 !”,按照下面的方法进行操作 。
返回 68
步骤一,选择 【 View】 菜单中的 【 ClassWizard】 菜单项 。
弹出 【 MFC ClassWizard】 对话框,在 【 Class name】 列表中选择类 CMainFrame,在 【 Object IDs】 列表中选择
ID_APP_ABOUT ;右边的 【 Messages】 栏中将出现
COMMAND 和 UPDATE_COMMAND_UI,双击
COMMAND选项 。 将弹出 Add Member Function 对话框 。
步骤二,接受系统缺省的函数名称 OnAppAbout,单击
【 OK】 按钮,返回 MFC ClassWizard对话框 。 这时在
MFC ClassWizard对话框中的 【 Member functions】 框中增加了一个函数 OnAppAbout。
步骤三,单击 【 Edit Code】 按钮,在代码编辑窗口中打开 OnAppAbout 函数 。 在编辑此函数之前,首先要在
MainFrm.cpp文件中添加一个 #include语句 。 具体代码如下,其中粗体部分为新增加的代码 。
返回 69
// MainFrm.cpp,implementation of the CMainFrame class
//
#include "stdafx.h"
#include "Dialog.h"
#include "MainFrm.h"
#include "MydataDialog.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
返回 70
步骤四,在代码编辑窗口中,编辑函数 OnAppAbout()。 具体代码如下,其中粗体部分为新增加的代码 。
void CMainFrame::OnAppAbout()
{// TODO,Add your command handler code here
CMydataDialog dlg;
if(dlg.DoModal()==IDOK)
{
CClientDC dc(this);
SIZE size=dc.GetTextExtent("您已经查看过个人资料对话框 !");
int ndex=m_MyStatusBar.CommandToIndex(ID_STATUSBAR_STR);
m_MyStatusBar.SetPaneInfo(index,ID_STATUSBAR_STR,SBPS_POP
OUT,size.cx);
m_MyStatusBar.SetPaneText(index,_T("您已经查看过个人资料对话框 !"),TRUE);
}
}
返回 71
说明:
在此函数中,首先生成了一个字体对话框的实例,并且显示为有模式对话框 。 当用户单击 【 确定 】 按钮退出此对话框时,要改变状态栏的字符串显示 。
首先调用函数 GetTextExtent()来获得字符串的长度,然后调用 CommandToIndex()函数获得窗格的索引,再通过调用函数 SetPaneInfo()来设置窗格的长度,风格等信息 。 在此例中,我们使用了风格 SBPS_POPOUT,它使创建的窗格看起来是从状态栏中凸出来的 。
最后调用函数 SetPaneText()来显示文本内容 。
步骤五,编译并运行此应用程序。
返回 72
本章小结在应用程序中,要实现菜单的功能,其步骤和方法是先利用菜单编辑器建立菜单资源,然后编写菜单命令的
WM_COMMAND消息映射函数及相应代码 。 在 MFC框架中,菜单命令消息是按照一定的顺序进行传递的 。 对于一个单文档应用程序,消息传递的顺序为:视图类 → 文档类 → 框架类 → 应用程序类 。
Visual C++的 MFC提供的菜单类 Cmenu的对象可以用来表示各种 Windows菜单,其中包括顶层菜单项及其相应的弹出式菜单 。 并且利用该类的成员函数可以在程序运行时处理有关菜单的操作 。
工具栏是应用程序中常用操作的快捷方式,创建工具栏的方法是先创建工具栏资源,然后在主框架窗口类
CMainFrame中创建响应 WM_CREATE的消息映射函数,
在该函数中,利用 MFC提供的工具栏类 CToolBar对象的返回 73
Create 成 员 函 数,创 建 工 具 栏 。 CToolBar 类是由
CControlBar类派生而来的,它用于描述工具栏 。
状态栏中的空间按从左向右的顺序分为信息行窗格和指示器窗格,处在状态栏最左侧的窗格,其位置序号为 0,
向右依次类推,它可以分割成几个窗格,用来显示许多信息 。 其创建方法是先创建状态栏资源,然后在主框架窗口类 CMainFrame中创建响应 WM_CREATE的消息映射函数,在该函数中,利用 MFC 提 供 的 工 具 栏 类
CStatusBar 对象的 Create 成 员 函 数,创 建 状 态 栏 。
CStatusBar类是由 CControlBar类派生而来的,它用于描述状态栏 。 状态栏中的窗格的个数及所显示的信息由在
MainFrm.cpp文件中定义的数组 indicators的元素的个数和元素的值来决定 。
返回 74
习题
6.1 利用 AppWizard向导建立一个单文档应用程序,并完成以下操作:
( 1) 利用资源编辑器向原有菜单栏中增加一个顶层菜单
,查看,,并在其下拉菜单 ( 弹出菜单 ) 中添加,显示鼠标坐标,菜单项 。
( 2) 在主框架窗口类即 CMainFrame类中,建立响应
WM_COMMAND和 WM_COMMAND_UI消息映射函数,
函数名自定,函数的功能是,当程序运行过程中,用户选择,显示鼠标坐标,菜单项时能在该菜单项的左边显示,√” 标记,当再次选择该菜单项时标记消失 。
( 3) 为,显示鼠标坐标,菜单项建立一个快捷键
,Ctrl+D” 。
返回 75
( 4) 利用资源编辑器向现有的工具栏的末尾添加一个按钮,按钮的图标自己设计 。 并进行有关的设定使该按钮的功能同选择,显示鼠标坐标,菜单项的功能相同 。
( 5) 在现有状态栏的基础上再增加一个信息行窗格,用于显示鼠标移动过程中鼠标的当前 X,Y坐标 。
( 6) 利用 ClassWizard向导在应用程序的视图类中添加响应 WM_MOUSEMOVE消息的消息处理函数,函数名自定,
该函数的功能就是把鼠标在移动过程中的位置 X,Y坐标显示到状态栏的新增信息行窗格中 。
6.2 在 VC环境中,利用 Help菜单查看和学习 CMenu类,
CToolBar类,CStatusBar类,CCmdUI类的内容,即其中的数据成员和成员函数 。