對於前面問題的分析:來源於http://blog.163.com/yuyang_tech/blog/static/216050083201211144120401/
解決方法1: //來源:http://www.cnblogs.com/yuzhoufeng/archive/2011/12/11/2284200.html
今天學習VC++ 2010 MFC單文檔應用程序中動態添加菜單,下面是代碼部分:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
int
CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
......
CMenu m_Menu;
m_Menu.CreatePopupMenu();
ASSERT(m_Menu.GetSafeHmenu());
GetMenu()->AppendMenuW(MF_POPUP,(
UINT
)m_Menu.m_hMenu,_T(
"文件"
));
m_Menu.AppendMenuW(MF_STRING,111,_T(
"新建"
));
m_Menu.AppendMenuW(MF_STRING,112,_T(
"打開"
));
m_Menu.Detach();
return
0;
}
|
但是GetMenu()返回始終未NULL,無法獲取菜單指針,網上查了下,說VS2010建的SDI/MDI與之前的不一樣,是類似BCG的一些東西,所以用之前的方法GetMenu()得到CMenu是NULL或者無效。
【解決方案】:
在CMainFrame類中找到CMFCMenuBar m_wndMenuBar;這個成員變量,將跟它相關的代碼注釋掉的話,然后運行,OK。
解決方法2: //來源:http://blog.csdn.net/grasshopperwarbler/article/details/6337754
這里說的是SDI的情況,如果在vs2010里面按着默認選項創建一個單文檔工程(Single Document).
問題分析:
出錯的代碼如下 :
GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND|MF_CHECKED);
加在CMainFrame::Oncreate()里面,整個程序就會崩潰,出現的異常類似如此:Unhandled exception at 0x58aba12c (mfc100ud.dll) in menu1.exe: 0xC0000005: Access violation reading location 0x00000004.
出錯的原因是,在執行這段代碼的時候,Menu並沒有生成。因為采用斷點來檢測的話,此時的GetMenu返回值不是一個正常的地址。為什么會這樣呢?
后來才發現visual studio2010里默認采用的是Menu格式在OnCreate()末端並未生成。vs2010默認采用的是增加了擴展功能的Menu,所以調用GetMenu()會得到空指針。
解決方法:
最原始的解決方法是采用回原來的Menu格式。就在新建工程的一個對話框中選擇回原始的菜單模式即可,如下圖:
不過經過更改后編譯會出現兩個錯誤,是關於:
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
兩句代碼是關於打印功能的。如果不涉及這方面的功能,可以直接把這兩句話注釋掉。然后在CMainFrame::OnCreate()末尾加上GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND|MF_CHECKED);
程序就可以順利通過了。
對於該問題在vs2010上面的解決方法出自http://blog.csdn.net/mjk1133/article/details/6681051
在VC6.0和VS2010里面動態添加菜單項是不一樣的,查看MSDN文檔可知,VS2010采用的是MFC9.0版,其中有很多新增的項具體信息請查看http://msdn.microsoft.com/en-us/library/ws8s10w4.aspx,本文就根據自己的測試詳細的比較一下二者的區別:
1.在VC6.0里面動態添加一個子菜單項:
在CMainFrame::OnCtreate()中添加代碼,另外要在Resource.h里面添加#define ID_MENU_ADDMENUITEM 32773
CMainFrame::OnCtreate(){
//下面是添加的代碼
CMenu *pMenu=AfxGetMainWnd()->GetMenu();
CMenu *pmSub=pMenu->GetSubMenu(1);
pmSub->AppendMenu(MF_STRING,ID_MENU_ADDMENUITEM,L"Add Menu &Item");
}//效果是在“Edit”菜單最下面添加了一個"Add Menu Item"子項
2.在VS2010里面添加一個子菜單項:
要對CMainFrame類的OnShowPopupMenu()進行重載,另外要在Resource.h里面添加#define IDS_EDIT_MYITEM_1 32773
BOOL CMainFrame::OnShowPopupMenu(CMFCPopupMenu* pMenuPopup)
{
// TODO: Add your specialized code here and/or call the base class
int iIndex = -1;
if (!CMFCToolBar::IsCustomizeMode()&&(iIndex=pMenuPopup->GetMenuBar()->CommandToIndex(ID_EDIT_PASTE))>=0)
{
pMenuPopup->InsertSeparator(iIndex+1);
pMenuPopup->InsertItem(CMFCToolBarMenuButton(IDS_EDIT_MYITEM_1,NULL,-1,_T("&MyItem 1")),iIndex+2);
} //使用CommandToIndex()來獲得菜單項的索引,然后根據索引來確定子菜單項的添加位置
return CFrameWndEx::OnShowPopupMenu(pMenuPopup);
}//效果是在“Edit”菜單最下面添加了一個分割線和一個"MyItem 1"子項
效果如圖,因為還沒有為其添加處理函數,所以呈灰色:
給添加的子菜單項添加消息處理函數:
在MainFrame.h里面添加消息處理函數聲明:
class CMainFrame : public CFrameWnd{
//…
protected:
afx_msg void OnEditMyItem1 ();
}
然后在MainFrame.cpp消息映射里面添加消息映射項:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//…
ON_COMMAND(IDS_EDIT_MYITEM_1, OnEditMyItem1)
END_MESSAGE_MAP()
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CMFCMenuBar的繼承關系:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++