6.3基本菜单操作(下)

6.3.4禁用菜单项

利用CMenu类的成员函数:EnableMenuItem来完成,能够使用、禁用和变灰显示菜单项。
UINT EnableMenuItem( UINT nIDEnableItem, UINT nEnable );
第一个参数由第二个参数决定。第二个参数;
MF_BYCOMMAND:指定第一个参数是菜单项标识ID。
MF_BYPOSITION:指定第一个参数是菜单项的位置索引。
MF_DISABLED:禁用菜单项,用户不能选择菜单项,但是菜单项没有变灰。
MF_GRAYED:禁用菜单项,用户不能选择菜单项,但是菜单项变灰。
MF_ENABLED:菜单项可用。

下面在框架类的OnCreate函数中禁用文件->打开菜单项。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{....
 GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLED);
 return 0;
}

运行发现并没有禁用打开菜单项。
原因:菜单项的更新都是由MFC的命令更新机制完成的,如果想自己更改菜单项的状态,就需要在框架类的构造函数中把m_bAutoMenuEnable这个变量初始化为FALSE。
运行后发现:编辑子菜单下菜单项不再加灰显示了,因为菜单项的更新现在不是由MFC的命令更新机制完成的。
在这里插入图片描述

6.3.5移除和装载菜单

移除菜单:CWnd类SetMenu成员函数来实现。
BOOL SetMenu( CMenu* pMenu );
参数指向一个新菜单对象,若为NULL,表示移除当前菜单。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{....
 GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLED);
 SetMenu(NULL);
 return 0;
}

运行,菜单栏就消失了。

装载一个菜单资源并显示:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{....
 GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLED);
 SetMenu(NULL);
 CMenu menu;
 menu.LoadMenu(IDR_MAINFRAME);
 SetMenu(&menu);
 return 0;
}

有个异常:menu是一个局部变量
第一种解决方案,将它改成框架类的成员变量。
第二种:在SetMenu函数将此对象设置为菜单之后,利用CMenu类成员函数Detach函数,将菜单句柄和菜单对象分离。这样局部菜单对象生命周期结束后,它不会销毁一个它不具有拥有权的菜单。
menu.Detach();

在这里插入图片描述

6.3.6MFC菜单命令更新机制

菜单项状态的维护依赖于CN_UPDATE_COMMAND消息。
让编辑子菜单下的剪切菜单项变为可用状态:
注释掉之前代码。
在ClassWizard中,选择ID_EDIT_CUT,右边选择UPDATE_COMMAND_UI消息。
Add Function->Edit Code

这样在框架类的消息映射中添加了一个ON_UPDATE_COMMAND_UI宏:

//{{AFX_MSG(CMainFrame)
 afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
 afx_msg void OnTest();
 afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI);
 //}}AFX_MSG

UPDATE_COMMAND_UI消息的OnUpdateEditCut消息响应函数:

void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 
{
 // TODO: Add your command update UI handler code here
}

CmdUI指针类型的参数:决定菜单是否使用、标记以及改变菜单项的文本。

MFC提供命令更新机制,在程序中实现菜单项的可用、禁用,只需要捕获UPDATE_COMMAND_UI消息,在该消息的响应函数中调用CCmdUI对象的响应函数:Enable,SetCheck,SetText函数。
virtual void Enable( BOOL bOn = TRUE );
参数为TRUE表示使菜单项可用,FALSE表示禁用菜单项。默认是TRUE。

void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 
{
 // TODO: Add your command update UI handler code here
 pCmdUI->Enable();
}

运行,剪切菜单项可以使用了。

然后发现工具栏上面的剪切按钮也可以使用了。然后发现二者的标识都是ID_EDIT_CUT,如果要把工具栏上工具按钮和菜单项相关联,只需要将二者的ID设置为同一个标识就可以了。

CCmdUI类有一个m_nID成员变量,用于保存当前菜单项、工具栏按钮,或者其他CCmdUI对象表示的UI对象标识。
例如,在使剪切菜单项可用之前,可以判断一下当前是否是剪切菜单项:

void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 
{
 // TODO: Add your command update UI handler code here
 if(ID_EDIT_CUT==pCmdUI->m_nID)
 {
  pCmdUI->Enable();
 }
}

CCmdUI类有一个m_nIndex成员变量,用于保存当前菜单项的位置索引。
例如,在使剪切菜单项可用之前,可以判断一下当前是否是剪切菜单项:

void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) 
{
 // TODO: Add your command update UI handler code here
 if(2==pCmdUI->m_nIndex)
 {
  pCmdUI->Enable();
 }
}

计算菜单项位置索引时,一定要把分隔栏菜单项计算在内。
这是子菜单剪切菜单变为可用了,但是工具栏的剪切按钮还是灰色。
这是因为菜单项和工具栏的位置索引计算方式不同。工具栏剪切的位置索引是4(包括分隔栏)。
所以为了保证二者状态一致,最好采用标识ID进行设置。在这里插入图片描述

6.3.7快捷菜单

经常用到鼠标右键显示快捷菜单。
实现右键快捷菜单功能:Project->Add to Project->Components and Controls。
弹出一个组件和控件库对话框:双击Visual C++ Components->Pop-up Menu,这个就是给派生于CWnd类的窗口添加一个右键菜单。->Insert。
弹出一个对话框:框架窗口接收不了鼠标消息,所以选择CMenuView类;下一行就是快捷菜单的资源ID。

插入了Pop-up Menu组建后,添加了以下两处内容:
第一处:在ResourceView选项卡的Menu分支下多了一个标识为CG_IDR_POPUP_MENU_VIEW的菜单资源。
第二处:为CMenuView类增加了一个函数:OnContextMenu。
在改函数内部调用了一个TrackPopupMenu函数来显示一个快捷菜单:
BOOL TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL );
第一个参数:指定菜单在屏幕上显示的位置
第二、三参数:指定快捷菜单显示位置的X和Y坐标。
第四个参数:快捷菜单的拥有对象,即窗口对象
第五个参数:指定一块矩形区域,区域内快捷菜单显示,否则不显示。

知道了TrackPopupMenu函数来显示一个快捷菜单,我们可以在Menu程序中实现自己的快捷菜单:
1、为Menu程序增加一个新的菜单资源:ResourceView->Menu单击鼠标右键->Insert Menu,这时Menu分支下多了一个IDR_MEBU1的菜单资源,接着就可以添加菜单项了。因为不是弹出菜单,去掉Pop-up。
2、为CMenuView类添加WM_RBUTTONDOWN的消息响应函数,然后参见OnContextMenu函数。

void CMenuView::OnRButtonDown(UINT nFlags, CPoint point) 
{
 // TODO: Add your message handler code here and/or call default
 CMenu menu;
 menu.LoadMenu(IDR_MENU1);
 CMenu* pPopup=menu.GetSubMenu(0);
 pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);
 CView::OnRButtonDown(nFlags, point);
}

运行,发现快捷菜单显示好像位置不太对,TrackPopupMenu函数中X,Y都是屏幕坐标,而鼠标单击的是窗口客户区坐标,即以程序窗口左上角为坐标原点。
所以需要把客户区坐标转化成屏幕坐标:ClientToScreen函数,在调用TrackPopupMenu函数之前添加ClientToScreen(&point);这一行代码,这样位置就显示正常了。
3、为Menu程序添加快捷菜单上各菜单项命令的响应函数:
ResourceView->IDR_MENU1->显示菜单项鼠标右键->ClassWizard->Cancel
然后利用ClassWizard分别为CMainFrame类和CMenuView类添加一个响应显示菜单项(IDM_SHOW)的函数OnShow,Message框中选择COMMAND消息。

void CMenuView::OnShow() 
{
 // TODO: Add your command handler code here
 MessageBox("View SHOW");
}
void CMainFrame::OnShow() 
{
 // TODO: Add your command handler code here
 MessageBox("Main SHOW");
}

运行,发现只有视类能对快捷菜单的命令进行响应。TrackPopupMenu函数中this指向视类窗口。如果想让框架类对快捷菜单命令进行响应,可以将代码修改为:

void CMenuView::OnRButtonDown(UINT nFlags, CPoint point) 
{
 // TODO: Add your message handler code here and/or call default
 CMenu menu;
 menu.LoadMenu(IDR_MENU1);
 CMenu* pPopup=menu.GetSubMenu(0);
 pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,GetParent());
 CView::OnRButtonDown(nFlags, point);
}
4. API之打印函数 AbortDoc 取消一份文档的打印 AbortPrinter 删除与一台打印机关联在一起的缓冲文件 AddForm 为打印机的表单列表添加一个新表单 AddJob 用于获取一个有效的路径名,以便用它为作业创建一个后台打印文件。它也会为作业分配一个作业编号 AddMonitor 为系统添加一个打印机监视器 AddPort 启动"添加端口"对话框,允许用户在系统可用端口列表中加入一个新端口 AddPrinter 在系统中添加一台新打印机 AddPrinterConnection 连接指定的打印机 AddPrinterDriver 为指定的系统添加一个打印驱动程序 AddPrintProcessor 为指定的系统添加一个打印处理器 AddPrintProvidor 为系统添加一个打印供应商 AdvancedDocumentProperties 启动打印机文档设置对话框 ClosePrinter 关闭一个打开的打印机对象 ConfigurePort 针对指定的端口,启动一个端口配置对话框 ConnectToPrinterDlg 启动连接打印机对话框,用它同访问网络的打印机连接 DeleteForm 从打印机可用表单列表中删除一个表单 DeleteMonitor 删除指定的打印监视器 DeletePort 启动"删除端口"对话框,允许用户从当前系统删除一个端口 DeletePrinter 将指定的打印机标志为从系统中删除 DeletePrinterConnection 删除与指定打印机的连接 DeletePrinterDriver 从系统删除一个打印机驱动程序 DeletePrintProcessor 从指定系统删除一个打印处理器 DeletePrintProvidor 从系统中删除一个打印供应商 DeviceCapabilities 利用这个函数可获得与一个设备的能力有关的信息 DocumentProperties 打印机配置控制函数 EndDocAPI 结束一个成功的打印作业 EndDocPrinter 在后台打印程序的级别指定一个文档的结束 EndPage 用这个函数完成一个页面的打印,并准备设备场景,以便打印下一个页 EndPagePrinter 指定一个页在打印作业中的结尾 EnumForms 枚举一台打印机可用的表单 EnumJobs 枚举打印队列中的作业 EnumMonitors 枚举可用的打印监视器 EnumPorts 枚举一个系统可用的端口 EnumPrinterDrivers 枚举指定系统中已安装的打印机驱动程序 EnumPrinters 枚举系统中安装的打印机 EnumPrintProcessorDatatypes 枚举由一个打印处理器支持的数据类型 EnumPrintProcessors 枚举系统中可用的打印处理器 Escape 设备控制函数 FindClosePrinterChangeNotification 关闭用FindFirstPrinterChangeNotification函数获取的一个打印机通告对象 FindFirstPrinterChangeNotification 创建一个新的改变通告对象,以便我们注意打印机状态的各种变化 FindNextPrinterChangeNotification 用这个函数判断触发一次打印机改变通告信号的原因 FreePrinterNotifyInfo 释放由FindNextPrinterChangeNotification函数分配的一个缓冲区 GetForm 取得与指定表单有关的信息 GetJob 获取与指定作业有关的信息 GetPrinter 取得与指定打印机有关的信息 GetPrinterData 为打印机设置注册表配置信息 GetPrinterDriver 针对指定的打印机,获取与打印机驱动程序有关的信息 GetPrinterDriverDirectory 判断指定系统中包含了打印机驱动程序的目录是什么 GetPrintProcessorDirectory 判断指定系统中包含了打印机处理器驱动程序及文件的目录 OpenPrinter 打开指定的打印机,并获取打印机的句柄 PrinterMessageBox 在拥有指定打印作业的系统上显示一个打印机出错消息框 PrinterProperties 启动打印机属性对话框,以便对打印机进行配置 ReadPrinter 从打印机读入数据 ResetDC 重设一个设备场景 ResetPrinter 改变指定打印机的默认数据类型及文档设置 ScheduleJob 提交一个要打印的作业 SetAbortProc 为Windows指定取消函数的地址 SetForm 为指定的表单设置信息 SetJob 对一个打印作业的状态进行控制 SetPrinter 对一台打印机的状态进行控制 SetPrinterData 设置打印机的注册表配置信息 StartDoc 开始一个打印作业 StartDocPrinter 在后台打印的级别启动一个新文档 StartPage 打印一个新页前要先调用这个函数 StartPagePrinter 在打印作业中指定一个新页的开始 WritePrinter 将发送目录中的数据写入打印机 5. API之文本和字体函数 AddFontResource 在Windows系统中添加一种字体资源 CreateFont 用指定的属性创建一种逻辑字体 CreateFontIndirect 用指定的属性创建一种逻辑字体 CreateScalableFontResource 为一种TureType字体创建一个资源文件,以便能用API函数AddFontResource将其加入Windows系统 DrawText 将文本描绘到指定的矩形中 DrawTextEx 与DrawText相似,只是加入了更多的功能 EnumFontFamilies 列举指定设备可用的字体 EnumFontFamiliesEx 列举指定设备可用的字体 EnumFonts 列举指定设备可用的字体 ExtTextOut 经过扩展的文本描绘函数。也请参考SetTextAlign函数 GetAspectRatioFilterEx 用SetMapperFlags要求Windows只选择与设备当前纵横比相符的光栅字体时,本函数可判断纵横比大小 GetCharABCWidths 判断TureType字体中一个或多个字符的A-B-C大小 GetCharABCWidthsFloat 查询一种字体中一个或多个字符的A-B-C尺寸 GetCharacterPlacement 该函数用于了解如何用一个给定的字符显示一个字串 GetCharWidth 调查字体中一个或多个字符的宽度 GetFontData 接收一种可缩放字体文件的数据 GetFontLanguageInfo 返回目前选入指定设备场景中的字体的信息 GetGlyphOutline 取得TureType字体中构成一个字符的曲线信息 GetKerningPairs 取得指定字体的字距信息 GetOutlineTextMetrics 接收与TureType字体内部特征有关的详细信息 GetRasterizerCaps 了解系统是否有能力支持可缩放的字体 GetTabbedTextExtent 判断一个字串占据的范围,同时考虑制表站扩充的因素 GetTextAlign 接收一个设备场景当前的文本对齐标志 GetTextCharacterExtra 判断额外字符间距的当前值 GetTextCharset 接收当前选入指定设备场景的字体的字符集标识符 GetTextCharsetInfo 获取与当前选定字体的字符集有关的详细信息 GetTextColor 判断当前字体颜色。通常也称为"前景色" GetTextExtentExPoint 判断要填入指定区域的字符数量。也用一个数组装载每个字符的范围信息 GetTextExtentPoint 判断一个字串的大小(范围) GetTextFace 获取一种字体的字样名 GetTextMetrics 获取与选入一种设备场景的物理字体有关的信息 GrayString 描绘一个以灰色显示的字串。通常由Windows用于标识禁止状态 PolyTextOut 描绘一系列字串 RemoveFontResource 从Windows系统中删除一种字体资源 SetMapperFlags Windows对字体进行映射时,可用该函数选择与目标设备的纵横比相符的光栅字体 SetTextAlign 设置文本对齐方式,并指定在文本输出过程中使用设备场景的当前位置 SetTextCharacterExtra 描绘文本的时候,指定要在字符间插入的额外间距 SetTextColor 设置当前文本颜色。这种颜色也称为"前景色" SetTextJustification 通过指定一个文本行应占据的额外空间,可用这个函数对文本进行两端对齐处理 TabbedTextOut 支持制表站的一个文本描绘函数 TextOut 文本绘图函数 6. API之菜单函数 AppendMenu 在指定的菜单里添加一个菜单项 CheckMenuItem 复选或撤消复选指定的菜单条目 CheckMenuRadioItem 指定一个菜单条目被复选成"单选"项目 CreateMenu 创建新菜单 CreatePopupMenu 创建一个空的弹出式菜单 DeleteMenu 删除指定的菜单条目 DestroyMenu 删除指定的菜单 DrawMenuBar 为指定的窗口重画菜单 EnableMenuItem 允许或禁止指定的菜单条目 GetMenu 取得窗口中一个菜单的句柄 GetMenuCheckMarkDimensions 返回一个菜单复选符的大小 GetMenuContextHelpId 取得一个菜单的帮助场景ID GetMenuDefaultItem 判断菜单中的哪个条目是默认条目 GetMenuItemCount 返回菜单中条目(菜单项)的数量 GetMenuItemID 返回位于菜单中指定位置处的条目的菜单ID GetMenuItemInfo 取得(接收)与一个菜单条目有关的特定信息 GetMenuItemRect 在一个矩形中装载指定菜单条目的屏幕坐标信息 GetMenuState 取得与指定菜单条目状态有关的信息 GetMenuString 取得指定菜单条目的字串 GetSubMenu 取得一个弹出式菜单的句柄,它位于菜单中指定的位置 GetSystemMenu 取得指定窗口的系统菜单的句柄 HiliteMenuItem 控制顶级菜单条目的加亮显示状态 InsertMenu 在菜单的指定位置处插入一个菜单条目,并根据需要将其他条目向下移动 InsertMenuItem 插入一个新菜单条目 IsMenu 判断指定的句柄是否为一个菜单的句柄 LoadMenu 从指定的模块或应用程序实例中载入一个菜单 LoadMenuIndirect 载入一个菜单 MenuItemFromPoint 判断哪个菜单条目包含了屏幕上一个指定的点 ModifyMenu 改变菜单条目 RemoveMenu 删除指定的菜单条目 SetMenu 设置窗口菜单 SetMenuContextHelpId 设置一个菜单的帮助场景ID SetMenuDefaultItem 将一个菜单条目设为默认条目 SetMenuItemBitmaps 设置一幅特定位图,令其在指定的菜单条目中使用,代替标准的复选符号(√) SetMenuItemInfo 为一个菜单条目设置指定的信息 TrackPopupMenu 在屏幕的任意地方显示一个弹出式菜单 TrackPopupMenuEx 与TrackPopupMenu相似,只是它提供了额外的功能 作者Blog:http://blog.csdn.net/daiguopeng/ 相关文章 用VC 6.0实现串行通信的三种方法 windows运行命令详解 Windows API函数大全四 Windows API函数大全三 Windows API函数大全二
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身影王座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值