返回首页

{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文件中读取菜单可以创建更通用。进入主菜单栏上的弹出窗口插入菜单搜索可以更通用。

回答

评论会员:游客 时间:2011/12/16
|弗兰克Paquier:好articlle
mIg_from_nsk
评论会员:游客 时间:2011/12/16
您可以使用,而不是处理所有控件的onchange事件onload事件document.getElementsByTagName("输入/TEXTAREA的/选择"){BR}1。您可以循环onload事件上的所有控件保存到某种类型的存储空间(可能是数组)他们的价值观2。onbeforeunload的,你可以使用此存储3。您可以包装成扩展控制这种行为,使用这个服务器与asp.netAjax库的控制,使所有的只是拖放到页面这样的控制imgsrc=http://www.orcode.com/upimg/2011_12_16_15_59_05_1.gif老实说,我有一个imgsrc=http://www.orcode.com/upimg/2011_12_16_15_59_05_1.gif祝你好运。
nickyt
评论会员:游客 时间:2011/12/16
mIg_from_nsk,反馈。有没有必要做一个的getElementsByTagName页面加载事件。我们已经拥有的形式收集和访问它。另外,通过循环的形式收集,crashedapp建议检查表单元素的初始值和当前值比较(见下面你的评论)。您还可以阅读我的​​回应他。再次感谢你阅读的文章,NickyT____________________________imgsrc=
crashedapp
评论会员:游客 时间:2011/12/16
重点并不总是意味着一个字段改变。另外的代码,可能会导致字段的值发生变化。所有浏览器上取得了巨大成功多年,我一直在做类似的东西。我只是检查的形式,改变之前,用户离开。HTML表单字段的默认状态都保存为您自动以支持表单的HTML复位按钮。由于这些值是通过JavaScript和DOM暴露给你为什么不利用他们的优势在哪里?表单字段的默认值属性如下:默认值(文本框,hiddenfields)defaultChecked(复选框,单选按钮)defaultSelected(Selectlists)只要遍历表单收集到currentValue默认值进行比较。它的速度非常快。我已经与表单域100S页,你甚至不通知的检查。顺便说一句,它的工作原理伟大的Ajax应用程序。所有这些,你要做的就是您的AJAX保存事件完成后,通过形式收集只是循环,使目前的表单字段的DefaultValue值。作品,因为表单元素的属性是读/写。
nickyt
评论会员:游客 时间:2011/12/16
crashedapp,这是真的,onkeydown并不一定意味着改变。这只是我做一个快速的样品。我也许应该把的onchange。我用一个简单的检查没有矿,因此,只要任何变化,航行距离前的检查是一个简单的布尔检查。然而,你的建议是一个好主意,循环遍历整个形式是不是真的,大的一击。唯一需要做的是验证自定义部件的变化。大部分的时间,可能不是一个问题,虽然在某些点的基础是一个表单元素。我知道INPUTTYPE="重置"/,重置表单值,但我从来没有想过要检查你提到的属性:默认值(文本框,hiddenfields)defaultChecked(复选框,单选按钮)defaultSelected(Selectlists)的意见表示感谢。后来,NickyT____________________________imgsrc=
Kelvin77
评论会员:游客 时间:2011/12/16
我的文章这个问题我已经玩了一会儿,发现你不仅要处理的刷新/内页导航按钮,但也菜单:......这些不同的事件导致被IE浏览器(泡沫)提出我不断的JavaScript和peform内onbeforeunload的检查页上改变目前的帐户,但然后要处理命令提出从。