最近做的一个VS2010的MDI项目,需要在打开文档时整体替换MainFrame的菜单项,并不只是更改某些子菜单项,而是包括主菜单项。通常来说打开一个Doc,相对应的菜单资源也会变。但是手上的项目不需要打开Doc,那么如何能整体替换菜单(对应不同的资源ID)呢?如下图所示:
默认状态:
打开文档后:
网上搜了一把,发现有不少朋友跟我遇到一样的问题,但是没有找到相应的答案。目前能找到的可行的办法,就是将菜单先全部删掉,然后再将自己需要的菜单一个一个Append上去,请参阅这里(http://blog.csdn.net/clever101/article/details/5795520)。这种方法可行,尤其是在小幅度改动菜单项的时候,非常方便,但是需要大规模的改呢?不妥。因为我很懒,不想敲那么多代码,于是自己研究。众所周知,VS2010的多文档视图,MainFrame的菜单不再是CMenu,而是可以浮动和停靠的CMFCMenuBar。所以如果想用SetMenu来做是行不通的,如果这么做,会出现这种效果:
这肯定不是我们要的效果。怎么办?查MSDN,发现用CMFCMenuBar的CreateFromMenu方法可以搞定这个问题:
HMENU hm=::LoadMenu(NULL, MAKEINTRESOURCE(nMenuID));
m_wndMenuBar.CreateFromMenu(hm, FALSE, FALSE);
nMenuID是你需要的菜单资源ID。需要说明的是CreateFromMenu的第二个参数:bDefaultMenu = FALSE。就是说如果在设置新菜单的时候,是否将新菜单做为默认菜单。举当前项目的例子:应用程序刚打开的时候,默认情况是没有文档打开的,那么菜单对应的是关闭状态(如:IDR_CLOSE)。当打开文档之后,通过调用这个方法,将新的菜单(如IDR_OPEN)设置到Mainframe。如果第二个参数设置为TRUE,当你关闭整个应用而没有去将原来对应关闭菜单(IDR_CLOSE)设置回去。下次启动应用时,默认的菜单就是(IDR_OPEN),但这个时候明明没有文档打开啊?
所以通常情况下都是把第二个参数按照默认值FALSE设定。这样有一个好处是,倘若你对应不同的文档,需要设置不同的菜单资源,当你在关闭文档时,只需要通过GetDefaultMenuResID方法就可以得到默认的菜单资源。
---------------------------------------------
最后说一句,写到这里突然感觉会不会是因为自己是新手,没找对方法,从而感觉像上面这种整体替换菜单资源很困难。很可能这种方法本来就很简单,以至于大家都不认为这是一种需要拿出来讨论的技巧,擦汗ing