失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 动态菜单项状态条提示工具条提示问题

动态菜单项状态条提示工具条提示问题

时间:2023-02-26 15:29:09

相关推荐

动态菜单项状态条提示工具条提示问题

想不想get新技能酷炫一下,今天小编就跟大家分享个简单的动态菜单项状态条提示工具条提示问题教程,一起来看看吧!超容易上手~

问题的提出:

一个应用程序想要动态改变菜单项。使用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){BOOL bVisible = IsToolbarVisible(...);// Note same mnemonic (&T) for both cmds!pCmdUI-SetText(bVisible ? "Hide &Toolbar" : "Show &Toolbar");}

仅此而已。下一步是提示。当你创建了一个菜单提示,你给它一个ID号。MFC使用这个ID来查找资源串获取命令提示。例如:

STRINGTABLE DISCARDABLE

BEGIN

ID_VIEW_TOOLBAR "Show or hide the toolbarnToggle 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 simplifiedvoid 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 wantSendMessage(WM_SETMESSAGESTRING, 0, (LPARAM)(LPCTSTR)sPrompt);m_nIDTracking = nItemID;} else {CFrameWnd::OnMenuSelect(nItemID, nFlags, hSysMenu);}}

文件中的实际代码调用一连串函数从菜单项来截获 文件名并建立所要的文本提示。别忘了还要调用CFrameWnd::OnMenuSelect来处理 未改变的提示的命令。

最后,对于如何动态改变工具提示文本的方法,CFrameWnd::OnToolTipText是MFC处理工具条通知的函数。其标准实现用匹配的命令ID加载资源串,截获n后的文本并将它拷贝调用者的TOOLTIPTEXT结构。你的任务是编写自己的 代码重载这个处理器。我把这个作为家庭作业。

本文示例代码或素材下载

如果觉得《动态菜单项状态条提示工具条提示问题》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。