MFC 对话框 创建菜单栏、工具栏以及菜单栏Checked 勾选显示工具栏

如题,我想在对话框上创建一个菜单栏和工具栏,并且能在菜单栏用checked 对工具的显示和隐藏,而且在工具栏的按钮上悬停有提示信息。
大概这个对话框是这样:

0.创建一个对话框
1.建立菜单栏
2.建立工具栏
3.菜单栏 让工具栏显示和隐藏
4.在工具栏的按钮悬停有提示信息

直接创建一个MFC 对话框程序,直接用VS 20* * 直接创建就行了,我用的VS2012。

一、创建菜单栏

在资源视图中插入一个MENU资源,ID设置为IDR_MENU1
在 C***Dlg::OnInitDialog()函数中添加如下代码:

    CMenu menu;  
    menu.LoadMenu(IDR_MENU1);  //IDR_MENU1为菜单栏ID号  
    SetMenu(&menu); 

这样运行菜单栏就在对话框上直接显示了。

二、创建工具栏

这里我找了很多代码,也看了很多资料,我是再OnInitDialg()函数中定义的 CToolBar m_toolbar;无论我怎么写,这个工具栏一直都不出来,也让我很疑惑,后来定义了全局变量就没事了,这里我还是有很大的疑惑。局部变量在执行这个函数的时候也创建了啊,为啥就不显示呢?稍后我在研究研究。
在资源视图里添加一个TOOLBAR ,IDR_TOOLBAR1,并且添加两个按钮,随便画上点图案就行。
在OnInitDialg()中添加如下代码:

if (! m_toolbar.CreateEx( this,TBSTYLE_FLAT ,  WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS,
        CRect(2,2,0,0)) ||    ! m_toolbar.LoadToolBar(IDR_TOOLBAR1) )
    {
        AfxMessageBox("failed to create toolbar\n");
        return FALSE;
    }
    //m_toolbar.ShowWindow(SW_SHOW); //显示工具栏,这里先注释掉,让菜单栏管理 SW_SHOW是宏定义1
    RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

这里不注释哪行,工具栏也可以显示了。

三、菜单栏的checked对工具的管理

在C***DLg.h中添加

void OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu); //显示toolbar

在.cpp 消息函数映射中添加 ON_WM_INITMENUPOPUP()

在.cpp中添加如下代码:

void CServerDlg::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
    //显示toolbar
    ASSERT(pPopupMenu != NULL);
    // Check the enabled state of various menu items.
    CCmdUI state;
    state.m_pMenu = pPopupMenu;
    ASSERT(state.m_pOther == NULL);
    ASSERT(state.m_pParentMenu == NULL);
    // Determine if menu is popup in top-level menu and set m_pOther to
    // it if so (m_pParentMenu == NULL indicates that it is secondary popup).
    HMENU hParentMenu;
    if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu)
    {
        state.m_pParentMenu= pPopupMenu; // Parent == child for tracking popup.
    }
    else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
    {
        CWnd* pParent = this;
        // Child windows don't have menus--need to go to the top!
        if (pParent != NULL && (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
        {
            int nIndexMax = ::GetMenuItemCount(hParentMenu);
            for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
            {
                if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu)
                {
                    // When popup is found, m_pParentMenu is containing menu.
                    state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
                    break;
                }
            }
        }
    }
    state.m_nIndexMax = pPopupMenu->GetMenuItemCount();
    for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;state.m_nIndex++)
    {
        state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex);
        if (state.m_nID == 0)
        {
            continue; // Menu separator or invalid cmd - ignore it.
        }
        ASSERT(state.m_pOther == NULL);
        ASSERT(state.m_pMenu != NULL);
        if (state.m_nID == (UINT)-1)
        {
            // Possibly a popup menu, route to first item of that popup.
            state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex);
            if (state.m_pSubMenu == NULL
                || (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0
                || state.m_nID == (UINT)-1)
            {
                continue; // First item of popup can't be routed to.
            }
            state.DoUpdate(this, TRUE); // Popups are never auto disabled.
        }
        else
        {
            // Normal menu item.
            // Auto enable/disable if frame window has m_bAutoMenuEnable
            // set and command is _not_ a system command.
            state.m_pSubMenu = NULL;
            state.DoUpdate(this, FALSE);
        }
        // Adjust for menu deletions and additions.
        UINT nCount = pPopupMenu->GetMenuItemCount();
        if (nCount < state.m_nIndexMax)
        {
            state.m_nIndex -= (state.m_nIndexMax - nCount);
            while (state.m_nIndex < nCount
                && pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
            {
                state.m_nIndex++;
            }
        }
        state.m_nIndexMax = nCount;
    }

}

在cpp中定义全局变量

    bool state=true; //默认显示toolbr

在菜单栏的下拉菜单添加响应事件COMMAND,如图这里写图片描述
这里写图片描述
这里一定要 一定要选好类
再添加响应事件 UPDATE_COMMAND_UI
代码如下:

void C***Dlg::Onsettoolbar()
{
    // TODO: 在此添加命令处理程序代码
    state = !state;
    m_toolbar.ShowWindow(state); // 0 隐藏 1 显示
}




void C***Dlg::OnUpdatesettoolbar(CCmdUI *pCmdUI)
{
    // TODO: 在此添加命令更新用户界面处理程序代码

    pCmdUI->SetCheck(state);

}

到这里工具栏就可以利用菜单栏里的checked 来控制是否显示

四、工具栏悬停提示信息

我在创建工具栏的时候就加上了可以有提示信息的属性CBRS_TOOLTIPS,也可以后续用m_toolbar.EnableToolTips(TRUE);实现。悬停显示信息的方法有多种,自己可以去网上查。
同样在.h文件中加入如下代码:

afx_msg BOOL OnToolTipNotify( UINT id, NMHDR * pNMHDR, LRESULT * pResult );//toolbar提示信息

cpp的消息函数映射中加入

ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnToolTipNotify)

cpp中加入如下代码:

BOOL CServerDlg::OnToolTipNotify(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
    //显示 toolbar  按钮的提示信息
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
    CString str;
    UINT nID =(UINT)pNMHDR->idFrom; //获取工具栏按钮ID
    if(nID)
    {
        nID = m_toolbar.CommandToIndex(nID); //根据ID获取按钮索引
        if (nID != -1)
        {
            switch(nID)
            {
            case 0:
                pTTT->lpszText  = "设置参数";
                break;
            case 1:
                pTTT->lpszText  = "管理服务";
                break;
            default:
                pTTT->lpszText = " ";
                break;

            }

            //获取工具栏文本           
            pTTT->hinst = AfxGetResourceHandle();
            return(TRUE);
        }
    }
    return(FALSE);
}

到这里我想要的功能全部实现。
这里写图片描述
这里写图片描述
这里写图片描述
欢迎大佬指点迷津。

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Vue中实现菜单栏的互斥效果可以使用v-model来实现,具体实现步骤如下: 1. 在每个菜单项中设置一个唯一的标识符id。 2. 在菜单项的父组件中定义一个data属性,用来记录当前选中项的id。 3. 在每个菜单项中绑定v-model,将当前菜单项的id与选中项的id绑定。 4. 在选中项id的setter函数中,判断当前选中项的id是否与之前选中项的id相同,如果不同则取消之前选中项的选中状态,将当前选中项设置为选中状态。 下面是示例代码: ```html <template> <div> <div v-for="item in menuList" :key="item.id"> <input type="radio" :id="'menu_'+item.id" :value="item.id" v-model="selectedId"/> <label :for="'menu_'+item.id">{{ item.name }}</label> </div> </div> </template> <script> export default { data() { return { menuList: [ { id: 1, name: '菜单项1' }, { id: 2, name: '菜单项2' }, { id: 3, name: '菜单项3' }, ], selectedId: null } }, watch: { selectedId(newVal, oldVal) { if (newVal !== oldVal) { // 取消之前选中项的选中状态 const oldSelected = document.querySelector(`#menu_${oldVal}`); oldSelected.checked = false; // 设置当前选中项为选中状态 const newSelected = document.querySelector(`#menu_${newVal}`); newSelected.checked = true; } } } } </script> ``` 在上面的代码中,我们通过v-model将菜单项的id与选中项的id进行了绑定,然后在watch中监听选中项的id的变化,根据变化来取消之前选中项的选中状态,将当前选中项设置为选中状态。这样就可以实现菜单栏的互斥效果了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

离水的鱼儿

一分也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值