MFC创建的MDI程序 新建一个子文档 主窗口标题自动会被追加上子文档的名字 取消此功能

overwrite CMainFrame::OnUpdateFrameTitle

void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
    CMDIFrameWnd::OnUpdateFrameTitle(bAddToTitle);

    ::SetWindowText(m_hWnd,m_strTitle);

}

现在很多应用程序的界面基本是用配置文件来规划界面的,在这个时候就得学会自定义菜单栏和工具栏之类的。


      VS Feature Pack是为微软新推出的界面库(听说是买BCG的授权,然后对之进行改造的),其中的主要的界面类可以和BCG的界面类可以对应起来,类的使用和BCG的也大同小异。但是有些做法还是很不一样,比如这次我要提到的自定义菜单栏。这里的自定义菜单栏是指去除系统默认的菜单栏,然后动态创建菜单栏。今天摸索了一下,大致搞清楚了(说实话,这方面网上的资料很少)。


      首先我们新建一个MFC的单文档工程:DynamicMenu,基本设置如下:

        这里要提一下的是VS Feature Pack的应用程序其中的菜单栏操作主要由CMFCMenuBar来负责。因此下面的编码也主要针对该类来进行。


       首先我们实现编码实现删除默认的所有系统菜单项,其代码如下:


view plaincopy to clipboardprint?
// 删除默认的所有系统菜单项    
static void DelAllMenu(HMENU hMenu)     
{     
    int Menucount = ::GetMenuItemCount(hMenu);     
    for (int i = Menucount-1;i>-1;i--)     
    {     
        ::DeleteMenu(hMenu,i, MF_BYPOSITION);     
    }       
}    
// 删除默认的所有系统菜单项 
static void DelAllMenu(HMENU hMenu) 

int Menucount = ::GetMenuItemCount(hMenu); 
for (int i = Menucount-1;i>-1;i--) 

   ::DeleteMenu(hMenu,i, MF_BYPOSITION); 
}    
}


然后我们定义两个菜单资源ID:


view plaincopy to clipboardprint?
#define ID_NEW_MENUBAR_OPEN     5000   
#define ID_NEW_MENUBAR_SAVE     5001 
#define ID_NEW_MENUBAR_OPEN 5000
#define ID_NEW_MENUBAR_SAVE 5001


为CMainFrame类添加一个创建菜单栏的成员函数:


view plaincopy to clipboardprint?
void CMainFrame::NewMenuBar()   
{   
    CMenu menu;   
    menu.CreateMenu();   
    CString strMenu;   
    strMenu = _T("打开文件");   
    menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_OPEN,strMenu);   
    strMenu = _T("保存文件");   
    menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_SAVE,strMenu);   
    CString strMenuBarTitle;   
    strMenuBarTitle = _T("文件");;   
    m_wndMenuBar.InsertButton (CMFCToolBarMenuButton (0, menu, -1,strMenuBarTitle));   

void CMainFrame::NewMenuBar()
{
CMenu menu;
menu.CreateMenu();
CString strMenu;
strMenu = _T("打开文件");
menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_OPEN,strMenu);
strMenu = _T("保存文件");
menu.AppendMenu(MF_ENABLED|MF_STRING,ID_NEW_MENUBAR_SAVE,strMenu);
CString strMenuBarTitle;
strMenuBarTitle = _T("文件");;
m_wndMenuBar.InsertButton (CMFCToolBarMenuButton (0, menu, -1,strMenuBarTitle));
}


我们在CMainFrame类的OnCreate函数调用这个函数,这里只给出部分代码:


view plaincopy to clipboardprint?
if (!m_wndMenuBar.Create(this))   
{   
    TRACE0("Failed to create menubar\n");   
    return -1;      // fail to create   
}   
m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);   
HMENU hm = m_wndMenuBar.GetDefaultMenu();   
// 删除默认菜单栏   
if (NULL!=hm)     
{     
    DelAllMenu(hm);     
}     
// 创建新的菜单栏   
NewMenuBar(); 
if (!m_wndMenuBar.Create(this))
{
   TRACE0("Failed to create menubar\n");
   return -1;      // fail to create
}
m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY);
HMENU hm = m_wndMenuBar.GetDefaultMenu();
// 删除默认菜单栏
if (NULL!=hm) 

   DelAllMenu(hm); 

// 创建新的菜单栏
NewMenuBar();


现在我们看看效果如何,如下图:


        我们发现默认菜单栏去掉了,但是新的菜单栏并没有出来。到网上搜资料,但是并没有搜到适用的,看了看Visual C++ 2008 Feature Pack Demo中提供的DynamicMenu的源码,了解了要增加AFX_WM_RESETMENU消息的处理函数,在函数里调用创建菜单栏,具体增加的代码如下:


view plaincopy to clipboardprint?
// MainFrm.h : interface of the CMainFrame classafx_msg    
// AFX_WM_RESETMENU消息的处理函数声明   
LRESULT OnResetMenu(WPARAM,LPARAM);    
// MainFrm.cpp : implementation of the CMainFrame class   
// 消息宏中增加   
ON_REGISTERED_MESSAGE(AFX_WM_RESETMENU,&CMainFrame::OnResetMenu)   
LRESULT CMainFrame::OnResetMenu(WPARAM,LPARAM)   
{   
    NewMenuBar();   
    return 0;   

// MainFrm.h : interface of the CMainFrame classafx_msg 
// AFX_WM_RESETMENU消息的处理函数声明
LRESULT OnResetMenu(WPARAM,LPARAM); 
// MainFrm.cpp : implementation of the CMainFrame class
// 消息宏中增加
ON_REGISTERED_MESSAGE(AFX_WM_RESETMENU,&CMainFrame::OnResetMenu)
LRESULT CMainFrame::OnResetMenu(WPARAM,LPARAM)
{
NewMenuBar();
return 0;
}


       我们再删除程序的注册表相关项重新编译(使用VS Feature Pack开发删除注册表这一项非常重要,Feature Pack的界面设计保存思路实际上和BCG是一样的,把上次用户设定的界面配置信息都保存在注册表,如果不删除注册表相关项,往往不能更新界面,注册表相关项一般在HKEY_CURRENT_USER\Software\Local AppWizard-Generated Applications\你的工程名称(英文版VS),HKEY_CURRENT_USER\Software\应用程序向导生成的本地应用程序\你的工程名称(中文版VS))。


     我们再看看效果,如下图:

     你可能会发现菜单是灰的,那是没有添加菜单的命令响应函数的缘故。本文的编译环境为:Windows XP + sp3, VS C++ 2008 + sp1。

      后来查了一下MSDN对AFX_WM_RESETMENU消息的解释,如下:

参考文献:

1. AFX Messages


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/clever101/archive/2010/08/07/5795520.aspx

在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的继承关系:

CObject

    CCmdTarget

           CWnd

                   CBasePane

                          CPane

                                 CMFCBaseToolBar

                                         CMFCToolBar

                                                   CMFCMenuBar

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值