一个关于对话框中GetMenu的问题

一个对话框工程,我在OnInitDialog中创建了一个菜单,代码如下:  
  CMenu Menu,PopupMenu1,PopupMenu2;  
   
  Menu.CreateMenu();  
  PopupMenu1.CreatePopupMenu();  
  PopupMenu2.CreatePopupMenu();  
   
  PopupMenu2.AppendMenu(MF_STRING,IDC_POPMENU_VIEW_NORMALICON,"Large   Icon");  
  PopupMenu2.AppendMenu(MF_STRING,IDC_POPMENU_VIEW_SMALLICON,"Small   Icon");  
  PopupMenu2.AppendMenu(MF_STRING,IDC_POPMENU_VIEW_LIST,"List");  
  PopupMenu2.AppendMenu(MF_STRING,IDC_POPMENU_VIEW_DETAILS,"Detail");  
  PopupMenu2.AppendMenu(MF_STRING,IDC_POPMENU_VIEW_THUMBNAILS,"Thumbnail");  
   
  PopupMenu1.AppendMenu(MF_STRING,ID_FILE_NEW,"&New");  
  PopupMenu1.AppendMenu(MF_POPUP,(UINT)PopupMenu2.m_hMenu,"View");  
  PopupMenu1.AppendMenu(MF_STRING,ID_FILE_OPEN,"&Open");  
  PopupMenu1.AppendMenu(MF_STRING,ID_FILE_CLOSE,"&Close");  
  PopupMenu1.AppendMenu(MF_STRING,ID_APP_EXIT,"E&xit");  
   
  Menu.AppendMenu(MF_POPUP,   (UINT)PopupMenu1.m_hMenu,   "&File");  
  Menu.AppendMenu(MF_STRING,   ID_EDIT_COPY,   "&Edit");  
   
  SetMenu(&Menu);  
  然后我映射了WM_CONTEXTMENU消息,以便用户单击右键时能弹出“File”下的菜单,但是在第一步GetMenu可以执行,但是一旦调用GetSubMenu(0)后,ASSERT出错,不知什么原因。  
  我试过添加一个HMENU成员,在OnInitDialog退出之前使用Menu.Detach保存菜单句柄,然后在OnContextMenu中使用Attach,结果GetSubMenu(0)还是出错。  
  不知什么原因,请大家帮忙!谢谢。 问题点数:50、回复次数:12Top

1 楼isdong(有些事情应该忘记)回复于 2003-11-27 10:54:32 得分 30

BOOL   CDialogDlg::OnInitDialog()  
  {  
  CDialog::OnInitDialog();  
   
  //   TODO:   Add   extra   initialization   here  
   
  CMenu Menu,PopupMenu1,PopupMenu2;  
   
  Menu.CreateMenu();  
  PopupMenu1.CreatePopupMenu();  
  PopupMenu2.CreatePopupMenu();  
   
  PopupMenu2.AppendMenu(MF_STRING,ID_FILE_NEW,"Large   Icon");  
  PopupMenu2.AppendMenu(MF_STRING,ID_FILE_NEW,"Small   Icon");  
  PopupMenu2.AppendMenu(MF_STRING,ID_FILE_NEW,"List");  
  PopupMenu2.AppendMenu(MF_STRING,ID_FILE_NEW,"Detail");  
  PopupMenu2.AppendMenu(MF_STRING,ID_FILE_NEW,"Thumbnail");  
   
  PopupMenu1.AppendMenu(MF_STRING,ID_FILE_NEW,"&New");  
  PopupMenu1.AppendMenu(MF_POPUP,(UINT)PopupMenu2.m_hMenu,"View");  
  PopupMenu1.AppendMenu(MF_STRING,ID_FILE_OPEN,"&Open");  
  PopupMenu1.AppendMenu(MF_STRING,ID_FILE_CLOSE,"&Close");  
  PopupMenu1.AppendMenu(MF_STRING,ID_APP_EXIT,"E&xit");  
   
  Menu.AppendMenu(MF_POPUP,   (UINT)PopupMenu1.m_hMenu,   "&File");  
  Menu.AppendMenu(MF_STRING,   ID_EDIT_COPY,   "&Edit");  
   
  SetMenu(&Menu);  
  Menu.Detach();  
  return   TRUE;     //   return   TRUE     unless   you   set   the   focus   to   a   control  
  }  
   
  void   CDialogDlg::OnContextMenu(CWnd*   pWnd,   CPoint   point)    
  {  
  CMenu   Menu;  
  Menu.Attach(GetMenu()->m_hMenu);  
  CMenu   *   pMenu   =   Menu.GetSubMenu(0);  
   
  }  
  此代码可以正常执行Top

2 楼carbon107(<软件开发思想.h>)回复于 2003-11-27 11:01:13 得分 20

???不会吧,你是象楼上说的那样吗??  
  在OnContextMenu里  
  CMenu   Menu;  
  Menu.Attach(GetMenu()->m_hMenu);  
  CMenu   *   pMenu   =   Menu.GetSubMenu(0);Top

3 楼codewarrior(会思考的草)回复于 2003-11-27 11:07:41 得分 0

to   isdong(有些事情应该忘记)   :  
  你的代码我试验过了,右键多点几次就会出错:(Top

4 楼codewarrior(会思考的草)回复于 2003-11-27 11:21:43 得分 0

试验过了,CMenu*   pMenu   =   GetMenu();得到的确实是最上层那一行菜单的指针,但是为什么一调用GetSubMenu(0)就Debug   Assertion   Failed呢?Top

5 楼isdong(有些事情应该忘记)回复于 2003-11-27 11:27:42 得分 0

要保证正确必须如下  
  void   CDialogDlg::OnContextMenu(CWnd*   pWnd,   CPoint   point)    
  {  
  CMenu   Menu;  
  Menu.Attach(GetMenu()->m_hMenu);  
  CMenu   *   pMenu   =   Menu.GetSubMenu(0);  
   
  Menu.Detach();  
  }  
  就是说这里,必须加上 Menu.Detach();  
  ,相信你不难理解,只是你一时忘记了罢  
  Top

6 楼codewarrior(会思考的草)回复于 2003-11-27 11:34:45 得分 0

非也非也,我没有忘记。  
  刚刚发现GetMenu得到的根本就不是一个菜单!  
  你试试:  
  CMenu*   pMenu   =   GetMenu();  
  ASSERT(pMenu);  
  ASSERT(::IsMenu(pMenu->GetSafeHmenu()));  
  Top

7 楼isdong(有些事情应该忘记)回复于 2003-11-27 11:42:46 得分 0

休息一下,关闭VC,重新打开工程,调试一下。我都试验了几十次了:),不会有问题的Top

8 楼codewarrior(会思考的草)回复于 2003-11-27 11:49:22 得分 0

现在问题明朗化了——就是——GetSubMenu(0)得到的不是一个popup   Menu的句柄。  
  我现在的试验代码如下:void   CTestDlg::OnContextMenu(CWnd*   pWnd,   CPoint   point)    
  {  
          CMenu*   pMenu   =   NULL;  
   
          ASSERT(::IsWindow(this->m_hWnd));<---没错确实是一个窗口,入口pWnd我这里没用到  
   
          pMenu   =   this->GetMenu();<--取最上层菜单  
          ASSERT(::IsMenu(pMenu->m_hMenu));   <--没错,确实是一个菜单的句柄  
     
          pMenu->AppendMenu(MF_STRING,ID_FILE_CLOSE,"hello");<--测试一下添几个项,成功.  
   
  //     CMenu*   pSub   =   pMenu->GetSubMenu(0);<--注释一去掉,ASSERT出错!!!  
  //     ASSERT(::IsMenu(pSub->m_hMenu));  
   
          DrawMenuBar();  
  }  
   
  所以唯一的解释就是,GetSubMenu(0)得到的不是一个子菜单的句柄。但现在的问题是,如前代码所示(你也看到演示结果了),这是不可能的,因为第0位就是File菜单啊,下面肯定有子菜单的。  
  Top

9 楼codewarrior(会思考的草)回复于 2003-11-27 11:53:38 得分 0

刚才           CMenu*   pMenu   =   GetMenu();  
  ASSERT(pMenu);  
  ASSERT(::IsMenu(pMenu->GetSafeHmenu()));  
  出错是因为我把前面OnInitDialog中的menu.detach给删了,不好意思我自己后来忘记了。  
   
  刚刚又添加了三行代码:  
  CString   str;  
  pMenu->GetMenuString(0,str,MF_BYPOSITION);  
  AfxMessageBox(str);  
  弹出的MessageBox是&File,证明pMenu指向的菜单的第0位确实是File菜单没错。  
  现在愈发不解了。  
   
  Top

10 楼codewarrior(会思考的草)回复于 2003-11-27 11:55:16 得分 0

会不会在OnInitDialog退出的时候,光Detach一个Menu没用?要全部Detach?试试看。Top

11 楼orbit(走了走了)回复于 2003-11-27 12:54:39 得分 0

用一个类成员保存菜单,用的时候直接操作不是更好吗?Top

12 楼isdong(有些事情应该忘记)回复于 2003-11-27 16:33:18 得分 0

这类固定的菜单写到资源文件里面比较好,根本没有这类奇怪的问题 

我最后的分析是一定要分离菜单句柄

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值