{A}
{S0}简介
本文讨论一个已经治疗了数千次的主题。其实,它不会带来任何真正的新的MFC应用程序中的动态菜单的整合,因为我已经重新使用很多现有代码。但是,我决定公布我的微薄的贡献,以分享我的经验中获得,同时制定以下两个主题:从一个外部XML文件配置菜单和工具栏。由多个外部BMP文件的串联创建一个位图。背景
很多样品处理这个问题已经被公布,我把这些以前的发展优势。两篇文章,主要是帮助我开始:。也感谢所有其他。使用代码
我没有放到一个库我的代码,但它可以很容易地复制子目录到任何MDI(或SDI)项目的命令重新使用。
要做到正确的连接,CMainFrame中必须修改的描述如下所示。首先,你创建一个直接在构造函数中MenuCommandSet://in MainFrame.h you add a private member
private:
MenuCommandSet* m_pMenuCommandSet;
//that you can create directly in the constructor
CMainFrame::CMainFrame()
{
m_pMenuCommandSet= new MenuCommandSet();
}
//... and destroy when finished
CMainFrame:: CMainFrame()
{
delete m_pMenuCommandSet;
}
MenuCommandSet初始化是在创建帧:{C}
现在,已经取得了初始化,我们使用它来创建和初始化的动态工具栏:int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
//then create ask for the first dynamic toolbar
MenuToolbar* pToolbar= m_pMenuCommandSet->GetMenuToolbar(MenuIdToolbar1);
if(pToolbar)
{
//create the toolbar control
if (!m_wndDynaToolBar.CreateEx(this,
TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP |
CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) )
{
TRACE("Failed to create m_wndToolBar2\n");
return -1; // fail to create
}
//attach the dynamic bitmap to the toolbar
m_wndDynaToolBar.SetBitmap(hBitmap);
//intialize it with the buttons found in the XML configuration file
m_wndDynaToolBar.SetButtons(pToolbar->GetIconIDs(),
pToolbar->GetIconCount());
}
...
m_wndDynaToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndDynaToolBar);
...
}
然后,我们添加的挂钩,进入状态栏显示的消息字符串:void CMainFrame::GetMessageString(UINT nID, CString& rMessage) const
{
if(m_pMenuCommandSet && m_pMenuCommandSet->IsInRange(nID)){
MenuItem oItem;
if(true==m_pMenuCommandSet->GetMenuItem(nID, oItem)){
rMessage= oItem.GetStatus();
}
return;
}
CMDIFrameWnd::GetMessageString(nID, rMessage);
}
要显示每个工具栏按钮的工具提示:BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
...
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnShowTooltips)
...
END_MESSAGE_MAP()
BOOL CMainFrame::OnShowTooltips(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
id; //parameter not used
pResult; //parameter not used
TOOLTIPTEXT* pTTT = (TOOLTIPTEXT*)pNMHDR;
UINT nID = (UINT)pNMHDR->idFrom;
CString sToolTip;
CString sFullText;
if(m_pMenuCommandSet && m_pMenuCommandSet->IsInRange(nID))
{
MenuItem oItem;
if(true==m_pMenuCommandSet->GetMenuItem(nID, oItem)){
sToolTip= oItem.GetTooltip();
strcpy_s(pTTT->szText, sizeof(pTTT->szText), (LPCTSTR)sToolTip);
}
return TRUE;
}
if(nID){
sFullText.LoadString(nID);
::AfxExtractSubString(sToolTip, sFullText, 1, '\n');
strcpy_s(pTTT->szText, _countof(pTTT->szText), sToolTip);
return TRUE;
}
return FALSE;
,当然,要处理动态菜单的点击次数:BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode,
void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
if(NULL==pHandlerInfo)
{
// Filter the commands sent to Window menu
if(m_pMenuCommandSet && m_pMenuCommandSet->IsInRange(nID))
{
if (nCode == CN_COMMAND){
// Handle WM_COMMAND message
m_pMenuCommandSet->DoCommandMenu(nID);
}else if (nCode == CN_UPDATE_COMMAND_UI){
// Update UI element state
m_pMenuCommandSet->DoUpdateMenu(nID, (CCmdUI*)pExtra);
}
return TRUE;
}
}
return CMDIFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
为了避免与其他标准的消息碰撞,不要忘记储备一堆的ID在resource.h文件直接。第一个(ID_CMDSET_RESERVED_1)MenuCommandSet让它知道它应该处理的命令。//in resource.h
#define ID_CMDSET_RESERVED_1 32770
#define ID_CMDSET_RESERVED_2 32771
#define ID_CMDSET_RESERVED_3 32772
#define ID_CMDSET_RESERVED_4 32773
#define ID_CMDSET_RESERVED_5 32774
...
//in CMainFrame::OnCreate()
if(false==m_pMenuCommandSet->Create("the_cfg_file_to_use.xml",
COMMAND_SET_BASE_ID))
return -1;
如果你要插入主菜单栏里面的一些菜单,您可以定义上的更新命令处理程序,在这里你可以插入您已经定义的弹出菜单。改进此代码最初创建与鱼[Rogue Wave的库使用。使用这个库,你可以分享几个工具栏,这是不是在纯MFC之间的单个位。为了处理多个动态工具栏,我们应该移动ToolbarBitmap MenuToolbar水平。从XML文件中读取菜单可以创建更通用。进入主菜单栏上的弹出窗口插入菜单搜索可以更通用。