问题描述:
孙鑫老师课程第6节里面讲到了设置标记菜单的方法如下:
GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION | MF_CHECKED);
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND | MF_CHECKED);
然而程序运行时出错如下:
First-chanceexception at 0x77c483ec (mfc90d.dll) in Menu.exe: 0xC0000005: Access violationreading location 0x00000004.
并且程序跳转到了GetSubMenu()函数定义的位置,感觉应该是指针出现问题了,将程序作了如下修改:
CMenu* menu_bar = GetMenu();
CMenu* file_menu = menu_bar->GetSubMenu(0);
调试过程发现menu_bar指针为空,姑且算是找到问题的原因了吧。不过不太明白为什么会出现获取不了系统菜单指针的情况呢?在网上找了一些大神的回答后做了整理,发现问题的原因并整理了如下两种解决办法:
原因:对比发现,程序资源(Resource View)里的菜单栏与应用程序所显示的并不一致,如图:
这似乎说明VS2008平台对这个菜单栏做了一定程序的修改?从程序中查找不难发现有一个关于菜单的变量值得深究:在MainFrm.h中定义了一个变量 CMFCMenuBar m_wndMenuBar;的确这个类对菜单栏进行了封装。
解决办法一:屏蔽掉程序中所有对这个变量进行使用的代码,再次编译运行发现应用程序的菜单栏恢复成了程序资源(Resource View)里的样式了,如下左图,增加标记菜单代码后运行同样通过,如下右图,新建菜单项成为标记菜单:
解决办法二:VS2008为什么会对菜单项做上述封装呢?在初始创建单文档应用程序的过程中有一些设置项可能没考虑而按照默认值来做,从而导致上述问题,如下图,用户界面特征设置项中,命令栏(Command bars (menu/toolbar/ribbon))有三个选项,系统默认选择第二项(Use a menu bar and toolbar),改为第一项(Use a classic menu),问题解决如下右图。
备注:方法二同时需要在Advanced Feature设置项中取消选中Printing and print preview项。
备注:孙老师在教学演示时采用的VC++6.0编程平台,程序运行正确。
参考:http://blog.163.com/yuyang_tech/blog/static/216050083201211144120401/