📄 06.3.4 禁用菜单项.txt
字号:
6.3.4 禁用菜单项
如果我们运行 Menu程序,并单击【文件】子菜单下的【打开】菜单项,将会出现"打开文件"对话框。这是 MFC AppWizard自动为我们实现的功能。下面,我们要禁用这个菜单项,以屏蔽文件打开功能,这可以利用 CMenu类的成员函数: EnableMenuItem来完成。该函数的作用是设置菜单项的状态:能够使用、禁用或变灰显示。其声明形式如下所示:
U工 NT EnableMenu工 tem( UINT nIDEnable工tem, U工NT nEnable );
同前面己介绍的 CMenu类的其他成员函数一样, EnableMenultem函数第一个参数的含义也是由第二个参数决定的。后者可以是 MF_DISABLED, MF_ENABLED或 MF GRAYED与 MF_BYCOMMAND或 MF BYPOSITION的组合。
. MF BYCOMMAND
指定第一个参数是菜单项的标识 ID。
. MF BYPOSITION
指定第一个参数是菜单项的位置索引。
. MF DISABLED
禁用菜单项,用户不能选择该菜单项,但该菜单项并没有变成灰色。
·肌1F ENABLED
使菜单项可用,用户可以选择这个菜单工页。
. MF GRAYED
禁用菜单项,用户不能选择该菜单项,并且该菜单项变成灰色的显示形式。例如, Menu程序运行时,它的【编辑】子菜单下的几个菜单项都是变灰显示的,如图 6.20所示。同时,我们会发现工具栏上与这几菜单项相对应的几个工具按钮也是不可用的。
al 提示:菜单的禁用状态和变灰状态是不同的。
一般来说,当用户看到某个菜单项是灰色显示的 (设置了 MF_GRAYED标志),就知
图 6.20变灰显示的菜单项
. 178 I ~~~
道这个菜单项是不能用的。如果菜单项是禁用状态 (设置了MFDISABLED标志),菜单项并没有变灰,用户就会认为这个菜单项是可用的,但是,当他选择这个菜单项时,程序并没有反应,用户当然就会认为这个程序的编写有问题。因此,从用户的角度考虑,我们通常把MF_GRAYED和MF_DISABLED这两个标志放在一起使用。但是,这么做并不是必需的。
应该在什么地方调用 EnableMenuItem函数以禁用某个菜单项呢?同上面的功能实现一样,在CMainFrame类的OnCreate函数中调用此函数可以达到我们的目的吗?实践出真知,为方便起见,我们先将上述例6-1到例6-7中自己添加的代码注释起来或去除,然后在CMainFrame类的 OnCreate函数中添加EnableMenultem函数调用,希望禁用【文件】子菜单项下的【打开】菜单项(【打开】菜单项在【文件】子菜单下的位置索引为1),使其不再弹出打开对话框,结果如例6-8所示。
19IJ 6-8
int CMainFrame : :OnCreate(LPCREATESTRUCT lpCreateStruct)
if (CFrameWnd::OnCreate(lpCreateStruct) -1)
returR-1;
if (!m_wndToolBar.CreateEx(this , TBSTYLE_FLAT , WS_CHILD WS_VISIBLE CBRS TOP CBRS_GRIPPER CBRS_TOOLTIPS CBRS_FLYBY I CBRS_SIZE_DYNAMIC) I I ! !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
TRACEO("Failed to create toolbar\ n 11 ) i
return -1; 11 fail to create
if (!m_wndStatusBar.Create(this) II
!m_wndStatusBar.Set工ndicators(ind工cators,
sizeof(indicators) / sizeof(UINT) ))
TRACEO( "Failed to create status bar\n )
11 ;
return -1; 11 fa工 1 to create
11 TODO: Delete these three lines if you don't want the toolbar to
11 be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY) ;
DockControlBar(&m_wndToolBar);
GetMenu()->GetSubMenu(O)->EnableMenu工tem(1, MF_BYPOSITION I MF_D工SABLED) ;
return 0;
「
" ‘ I 179
黯鹅
Build并运行 Menu程序,选择【文件】子菜单下的【打开】菜单项,但是这时仍会出现"打开文件"对话框,这说明【打开】菜单项并未被禁用。作为程序员,一旦程序出现问题,我们就要思考可能出错的原因。这里,我们首先可能会想到是不是使用的菜单位置索引不对,但是【文件】子菜单的位置索引确实是 0,而【打开】菜单项在其子菜单下的位置索引确实也是1,因此,可以排除菜单项索引出错的可能:那么接下来,我们可能会想,是不是 MF_DISABLED和 MF_GRAYED这两个标志必须一起使用?读者可以试验一下,在上述代码中再加上 MF GRAYED标志,结果会发现也不是这个原因:最后,我们还是求助于 MSDN吧。在 MSDN中找到关于 EnableMenultem函数的说明,在该说明的最后提供的例子中,有一处提示信息,原说明文字如下:
// NOTE: m_bAutoMenuEnable is set to FALSE in the constructor of
// CMainFrame so no ON_UPDATE_COMMAND_U工 or ON_COMMAND handlers are
// needed, and CMenu::EnableMenultem() will work as e)甲ected.
国际:笔者使用的 MSDN版本是 2∞1年 1月的,以前版本的 MSDN村
能没有这样的信息。
这个提示信息是说,一旦在 CMainFrame类的构造函数中把成员变量 m bAutoMenuEnable设置为 FALSE后,就不需要对 ON_UPDATE_COMMAND_UI或 ON COMMAND消息进行响应处理了, CMenu类的 EnableMenultem函数将能够正常工作。
实际上, MFC为菜单提供了一种命令更新的机制 (下面的内容将详细讲解),所以,程序在运行时,根据此机制去判断哪个菜单可以使用,哪个菜单不能够使用,然后显示其相应的状态。默认情况下,所有菜单项的更新都是由 MFC的命令更新机制完成的。如果我们想自己更改菜单项的状态,那就必须先把 m bAutoMenuEnable变量设置为 F丛SE,之后,我们自己对菜单项的状态更新才能起作用。因此,我们就在程序 Menu的 CMainFrame类构造函数中把 m bAutoMenuEnable这个变量初始化为 FALSE,代码如例 6-9所示。
例 6-9
CMainFr ame: :CMainFr ame( )
// TODO: add member in工t工al工zat工on code here m_bAutoMenuEnable = FALSE;
再次 Build井运行 Menu程序,选择【文件】子菜单下的
"资<<1)...Q\呻
佛lFi倒吨
⑤
【打开】菜单项,将会发现程序没有出现"打开文件"对话框,揭,为曲阜.
这就说明 EnableMenultem函数起作用了,【打开】菜单被禁
用了。但是,这种菜单显示方式让人感觉有点别扭,从这个
菜单显示的形式(如图 6-21所示)上看,好像它应该是能够
使用的,但是单击它时却又没有反应。图 6.21禁用但未使其变灰显因此,通常将 MF DISABLED和 MF GRAYED这两个示的【打开】菜单项
180 I ~…如
VCII深λ详解
标志一起使用。修改上述例 6-8所示 OnCreate函数中加灰显示的那行代码,在 Enable Menultem函数中加上岛1F GRAYED标志。结果如例6-10所示。
~IJ 6-10
int CMainFrame : :OnCreate(LPCREATESTRUCT lpCreateStruct)
{
工f (CFrameWnd: : OnCreate(lpCreateStruct) -1)
return -1:
if (!m_wndToolBar.CreateEx(this , TBSTYLE_FLAT , WS_ CHILD WS_VIS工BLE CBRS TOP CBRS_ GRIPPER I CBRS_TOOLTIPS CBRS_FLYBY I CBRS_SIZE_DYNAMIC) I I !m_wndToolBar . LoadToolBar(IDR_MAINFRAME))
TRACEO ( "Fa工led to create toolbar\ n 11 ) i
return -1 : // fail to c reate
if (!m_wndStatusBar . Create(this) II
!m_wndStatusBar.Setlndicators(indicators ,
sizeof(indicators) / sizeof(UINT)))
TRACEO( "Fai1ed to create status bar\ n 11 ) ;
return -1 ; // fai1 to create
// TODO : Delete these three lines if you don ' t want the toolbar to
/ / be dockable
m_ wndToolBar . EnableDocking (CBRS_ALIGN_ANY) ;
EnableDocking(CBRS_AL工GN_ANY) :
DockControlBar(&m_wndToolBar) :
GetMenu()->GetSubMenu(O)->EnableMenu工tem(l, MF一BYPOSITION MF DISABLED MF_GRAYED) :
return 0 :
再次Build井运行Menu程序,打开【文件】子菜单,这时可以发现【打开】菜单项已经变灰了,单击这个菜单项,发现它也不起作用了。
当然,这里也可以利用菜单项标识来调用 EnableMenuItem函数,方法是把该函数的第一个参数换成【打开】菜单项的标识 ID,并把 MF BYPOSITION标志换成 MF BYCOMMAND标志。
另外,当在 CMainFrame类的构造函数中把成员变量 m bAutoMenuEnable设置为 FALSE后,将发现 Menu程序的编辑子菜单下的几个菜单项不再以灰色显示了。因为当 m_bAutoMenuEnable设置为FALSE后, MFC就不再利用它的菜单命令更新机制去判断哪
............ 1181
个菜单可以使用,哪个菜单不能够使用,所以其也就不能根据菜单项的状态以不同的外观来显示。而菜单能否使用这些判断操作,就需要我们自己去完成了。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -