上一篇:关于CEdit控件的透明 --作 >>
动态菜单项、状态条提示、工具条提示问题
| 动态菜单项、状态条提示、工具条提示问题 | |
| 赵湘宁 | |
| 本文例子代码 | |
| 问题的提出: 一个应用程序想要动态改变菜单项。使用CCmdUI::SetText("Menu Text")可以改变菜单文本,但是如何动态改变工具条和状态条的文本呢? 有几种策略,避免,欺骗,面对...... 首先,避免:为什么你非要动态改变菜单项?一般说来,这是个坏主意,动态菜单容易把人搞糊涂。我正在使用你的产品,本来用得好好的突然菜单项变了。不管什么时候,每当我看到一个改变菜单的应用时,都要琢麽为什么他们需要这样的用户界面设计。 然而,每一个规则都有例外,许多例子的动态改变菜单项都很酷。例如,在大多数面向文档的应用程序中“文件”菜单的最后一项MRU(最近使用的文件列表)。但作为一个用户,面对动态菜单项的弊端是显而易见的。我把避免动态菜单提升为设计准则。即便是采用了动态菜单的设计,也要让用户注意不到菜单项是改变,否则,It's bad design。反之,如果用户注意不到菜单项的改变,It's OK。 但是动态改变状态条提示又如何呢?在MRU菜单中,无论什么文件,状态条一般都提示“打开选择的文档”。这是另一个要避免的策略。只有特别本位或任性的程序员会操心实现一个动态提示的菜单,如:“打开某某文件”,而不去用完全可行并且有效的提示“打开这个文档”。你完全有权利不遵循这种惯例,也就是说,如果你非要改变状态条提示的话,那就请往下继续看吧,你会明白的。 使用动态菜单的另一场合是当你想设置某个布尔状态时。例如,隐藏或显示工具条,当工具条可见时显示“隐藏工具条”,反之显示“显示工具条”。更为普通的方法是用单个命令以校验标记来实现,当工具条可见时显示标记(如下图)。 |
|
|
|
|
|
GUI的高手们常常争论哪种方法更好。可能它没有什么差别,但是即使你决定使用动态提示(如隐藏/显示工具条),你也能使用单个的命令ID,ID_VIEW_TOOLBAR,和单个的提示“隐藏或显示工具条”。我认为没有必要去实现动态提示。 在所有建议中,你要做的第一件事情是好好重新考虑用户的界面。你确实需要动态菜单项吗?以及你确实需要菜单的动态提示吗?除非两个问题的答案都是“是”。否则就止住,别再浪费时间。 要改变菜单文本是容易的。只要实现ON_UPDATE_COMMAND_UI处理器并调用CCmdUI::SetText即可: void CFrameWnd::OnUpdateToolbar(CCmdUI* pCmdUI) 仅此而已。下一步是提示。当你创建了一个菜单提示,你给它一个ID号。MFC使用这个ID来查找资源串获取命令提示。例如:STRINGTABLE DISCARDABLE BEGIN ID_VIEW_TOOLBAR "Show or hide the toolbar\nToggle ToolBar" END 如果你的菜单命令也有工具条按钮,MFC用“\n”(新行标记)后的文本作为工具条提示文本。因为MFC允许每个命令只能有一个串,如何动态改变提示呢?最简单的方法是编写一个提示在两种情况下都工作,象前面讨论的隐藏、显示工具条的例子。但这种方法显得很笨拙。 获得动态提示的一个方法是将命令分成几个命令-例如,ID_HIDE_ TOOLBAR 和ID_SHOW_TOOLBAR,只是一种欺骗策略。这些命令的命令处理器最终要做的事情是改变菜单项的ID为其它命令项的ID。具体实现细节我就不讲了,自己做吧。 使用两个ID可能是一种简单的方法,但它不适用于所有情况。例如在MRU文件菜单中,对于每个可能的文件名字你会需要不同的ID。 本文提供一个例子程序,DynPrompt,如下图, |
|
|
|
|
| 状态条采用了动态提示,为了理解DynPrompt是如何工作的,你必须对MFC的菜单提示有一些研究。当用户的鼠标
移动到一个菜单项时,Windows发送WM_MENUSELECT和菜单项的ID。MFC的CFrameWnd处理如下: // much simplified void CFrameWnd::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu) { SendMessage(WM_SETMESSAGESTRING, nItemID); } 我做了一些简化;函数的实际代码超过了60行,但基本的意思是框架发送WM_SETMESSAGESTRING消息到自身,用WPARAM传递命令ID。SETMESSAGESTRING 是MFC的一个私有消息,它在afxpriv.h中定义。这个消息在状态条窗格中设置 要显示的文本。你可以用WPARAM传递资源串的ID,或者用LPARAM传递实际的串。 // resource string ID SendMessage(WM_SETMESSAGESTRING, ID_MYSTRING); // string SendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)_T("Hello, world")); 所以,如果要实现动态菜单提示,必须重载CFrameWnd::OnMenuSelect和 用提示串发送WM_SETMESSAGESTRIN消息。 void CMainFrame::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu) { if (/* nItemID has a dynamic prompt */) { CString sPrompt = // whatever you want SendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)(LPCTSTR)sPrompt); m_nIDTracking = nItemID; } else { CFrameWnd::OnMenuSelect(nItemID, nFlags, hSysMenu); } } MainFrm.cpp文件中的OnMenuSelect实际代码调用一连串函数从MRU菜单项来截获 文件名并建立所要的文本提示。别忘了还要调用CFrameWnd::OnMenuSelect来处理 未改变的提示的命令。 最后,对于如何动态改变工具提示文本的方法,CFrameWnd::OnToolTipText是MFC处理工具条通知的函数。其标准实现用匹配的命令ID加载资源串,截获“\n”后的文本并将它拷贝调用者的TOOLTIPTEXT结构。你的任务是编写自己的 代码重载这个处理器。我把这个作为家庭作业。 |
下一篇:CAnimateCtrl::Open的使用问题 >>
相关文章:
- · 对话框打印预览及打印
- · 关于如何换肤、子类化的解决方案
- · 制作 MSN、QQ 的消息提示窗口
- · 如何对 BCGControlBarPro 进行换肤
- · 定制个性化的对话框窗口类
- · 透明窗体的又一实现
- · 橡皮区矩形 CRectTracker C# 实现
- · 轻松实现类 MSDN 2002 界面(二)
- · 轻松实现类 MSDN 2002 界面
- · 数据库开发之窗体编程
- · 一个打印报表的简单的类
- · SDK 程序使用SkinMagic工具包换皮肤
- · Windows SDK笔记(七):创建MDI窗口
- · Windows SDK笔记(六):使用对话框资源建立窗口
- · Windows SDK笔记(五):非模式对话框
- · Windows SDK笔记(四):模式对话框
- · 也谈如何隐藏显示在任务栏中的对话框程序
- · 一个托盘程序演示 -闹钟 Alert
- · think window procedure
- · 再谈 CFileDialog 对话框的定制
- · 获得 Win32 窗口句柄的更好的方法
- · 个人考勤软件开发实例配套代码 2.1版(Update…
- · 介绍一个操作DHTML表格的C++对象
- · Windows资源管理器Web视图界面
- · 为你的程序换个皮肤
- · 程序启动画面
- · 实现标题条的显示与隐藏
- · 在EVC3.0中创建MDI程序
- · 无模式对话框的创建与使用
- · 界面专家简介
- · 再谈客户区对话框拖动操作
- · Windows 2000/XP中对窗口进行透明化
- · 用线程实现动态改变图标
- · 不规则对话框的又一实现
- · 用SkinMagic工具包创建换皮肤程序
- · 最简单的界面增强库EasySkin
- · 在VC++.net中制作启动屏幕的新方法
- · 椭圆窗体的实现
