查遍了msdn。用过CToolBarCtrl::EnableButton
CToolBarCtrl::SetState都不起作用

解决方案 »

  1.   

    有个办法可能不是太好,但是可以
    用SetButtonInfo把要禁止按钮的ID改成无效
      

  2.   

    好像真没有,不知有hiden的方法来替换如何?
    CMainFrame * pMainFrame=(CMainFrame *)AfxGetMainWnd(); if(pMainFrame->m_wndToolBar.GetToolBarCtrl().IsButtonEnabled(ID_GETDATESOURCE))
    {
    MessageBox("test");
    pMainFrame->m_wndToolBar.GetToolBarCtrl().SetState(ID_,TBSTATE_HIDDEN);
    }
    if(pMainFrame->m_wndToolBar.GetToolBarCtrl().IsButtonHidden(ID_))
    {
    MessageBox("test1");
    pMainFrame->m_wndToolBar.GetToolBarCtrl().SetState(ID_,TBSTATE_ENABLED); }
      

  3.   

    to  kongyunzhongque(云雀):如果hide就简单了。直接设计button的state就可以了
      

  4.   

    to aaasng(做一个好学生):这个效果不太好。。而且在我的控制逻辑中,比较麻烦。
      

  5.   

    在PreTranslateMessage(MSG* pMsg) 函数中 修改 工具栏 的 状态m_wndToolBar.GetToolBarCtrl().EnableButton( ID_FILE_NEW, FALSE );这样就可以了。BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) 
    {
    // TODO: Add your specialized code here and/or call the base class
    m_wndToolBar.GetToolBarCtrl().EnableButton( ID_FILE_NEW, FALSE );
    return CFrameWnd::PreTranslateMessage(pMsg);
    }
      

  6.   

    pToolBarCtrl->SetCmd(nIndex, 1);
      

  7.   

    错了,是
    pToolBarCtrl->SetCmdID(nIndex, 1);
      

  8.   

    你要搞清你为什么不能禁用toolbar上的按钮
    看看mfc的源代码
    所有的界面更新操作mfc都有自己的一套机制。通过对idle消息的处理发送WM_COMMAND消息(code=CN_COMMAND_UI),因为WM_COMMAND消息在mfc里面有自己定义好的流动方式,所以对界面的更新操作每时每刻都在进行。尽管你用CToolBarCtrl::EnableButton或者CToolBarCtrl::SetState改变按钮的状态,mfc在线程没有消息的时候也会干涉的。
    它的干涉方式如下:
    void CControlBar::OnInitialUpdate()
    {
    // update the indicators before becoming visible
    OnIdleUpdateCmdUI(TRUE, 0L);//这里调用下一个函数
    }
    LRESULT CControlBar::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM)
    {
    // handle delay hide/show
    BOOL bVis = GetStyle() & WS_VISIBLE;
    UINT swpFlags = 0;
    if ((m_nStateFlags & delayHide) && bVis)
    swpFlags = SWP_HIDEWINDOW;
    else if ((m_nStateFlags & delayShow) && !bVis)
    swpFlags = SWP_SHOWWINDOW;
    m_nStateFlags &= ~(delayShow|delayHide);
    if (swpFlags != 0)
    {
    SetWindowPos(NULL, 0, 0, 0, 0, swpFlags|
    SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
    } // the style must be visible and if it is docked
    // the dockbar style must also be visible
    if ((GetStyle() & WS_VISIBLE) &&
    (m_pDockBar == NULL || (m_pDockBar->GetStyle() & WS_VISIBLE)))
    {
    CFrameWnd* pTarget = (CFrameWnd*)GetOwner();
    if (pTarget == NULL || !pTarget->IsFrameWnd())
    pTarget = GetParentFrame();
    if (pTarget != NULL)
    OnUpdateCmdUI(pTarget, (BOOL)wParam); //这里调用CToolBar的下一个成员函数
    }
    return 0L;
    }void CToolBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
    {
    CToolCmdUI state;
    state.m_pOther = this; state.m_nIndexMax = (UINT)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
    for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; state.m_nIndex++)
    {
    // get buttons state
    TBBUTTON button;
    _GetButton(state.m_nIndex, &button);
    state.m_nID = button.idCommand; // ignore separators
    if (!(button.fsStyle & TBSTYLE_SEP))
    {
    // allow reflections
    if (CWnd::OnCmdMsg(0,
    MAKELONG((int)CN_UPDATE_COMMAND_UI, WM_COMMAND+WM_REFLECT_BASE),
    &state, NULL))
    continue; // allow the toolbar itself to have update handlers
    if (CWnd::OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))
    continue; // allow the owner to process the update
    state.DoUpdate(pTarget, bDisableIfNoHndler);
    }
    } // update the dialog controls added to the toolbar
    UpdateDialogControls(pTarget, bDisableIfNoHndler);
    }
    //主要的操作就在这里面
    BOOL CCmdUI::DoUpdate(CCmdTarget* pTarget, BOOL bDisableIfNoHndler)
    {
    ASSERT_VALID(pTarget); if (m_nID == 0 || LOWORD(m_nID) == 0xFFFF)
    return TRUE;     // ignore invalid IDs m_bEnableChanged = FALSE;
             //这里调用我们自己写的OnCmdUI()如果没有写bResult返回FALSE;
             //m_bEnableChanged是CCmdUI的成员变量通过pCmdUI->Enable来改变他
    BOOL bResult = pTarget->OnCmdMsg(m_nID, CN_UPDATE_COMMAND_UI, this, NULL);
    if (!bResult)
    ASSERT(!m_bEnableChanged); // not routed//bDisableIfNoHandle 就是前面OnInitialUpdate里面的TRUE;
    //如果bDisableIfNoHndler(对应的命令没有处理函数就禁止该选项)为true而且
    //m_bEnableChanged为为False(默认)执行下面的代码 if (bDisableIfNoHndler && !m_bEnableChanged)
    {
    AFX_CMDHANDLERINFO info;
    info.pTarget = NULL;
          //注意bHandle的返回值为TRUE表示消息处理链中有这样的函数
    BOOL bHandler = pTarget->OnCmdMsg(m_nID, CN_COMMAND, this, &info);#ifdef _DEBUG
    if ((afxTraceFlags & traceCmdRouting) && !bHandler)
    TRACE1("No handler for command ID 0x%04X, disabling it.\n", m_nID);
    #endif
    // Enable or Disable based on whether there is a handler there
       //这是一行关键的代码禁止和允许都在这里面
                //如果不想要mfc自动改变状态就在前面想办法吧 ^&^
                Enable(bHandler);
    }
    return bResult;
    }
    好累阿
    我想经过上面的分析你应该知道怎么做了吧
      

  9.   

    我的应用只能通过CToolBar的指针来进行操作。其他的消息都不能处理。。比如,根本无法处理PreTranslateMessage消息。。工具条是在插件(一个com组件)中动态生成的。而且我只能在这个插件中对工具条做处理。。楼上几位说的方法都行不通
      

  10.   

    checkyvc6(checkyvc6)说的很有道理。。晚上来揭贴。。我再想想办法
      

  11.   

    哦,是这样啊,那么你为什么不自己写一个CExToolBar呢,这样在里面重载OnUpdateCmdUI就可以自由控制一个一个具体的id呢
    我想如果你用CToolBar除非做钩子和挂接,否则很难实现,我是这样想的.
      

  12.   

    呵呵,我做过,写个函数,把mfc的源码拷出来就ok了。
      

  13.   

    现在又有一个问题。我通过ON_UPDATE_COMMAND_UI_RANGE调用一个com的接口方法,该接口方法判断是否禁用工具栏按钮。但是这样做被禁用的按钮闪烁的很厉害。。ON_UPDATE_COMMAND_UI_RANGE(1,1000,OnCommandUIRange)void CMainFrame::OnCommandUIRange()
    {
        if(m_spMedia) // 接口指针有效
        {
    m_spMedia->UpdateUICommand(); //调用组件中的更新
        }
    }// 组件中
    STDMETHODIMP CMedia::UpdateUICommand()
    {
        if( m_bUpdate )
        {
    CMenu* pMenu = m_pMainMenu->GetSubMenu(1);
    pMenu->EnableMenuItem(iId,MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);

    m_pToolBar->GetToolBarCtrl().EnableButton(iId,FALSE);
        }

        return S_OK;
    }
      

  14.   

    还有一个很神奇的问题。pMenu->EnableMenuItem(iId,MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);如果iId是子菜单中最后一项,则禁用不起作用。。我是不是采倒狗屎了??
      

  15.   

    对于菜单来说没有必要这样做,
    CFrameWnd::有个公有成员变量来控制是否使用cmdui来更新菜单如果m_bAutoMenuEnable 
    你只要赋值为FALSE就可以了;
      

  16.   

    在com里,哪里来m_bAutoMenuEnable之类的变量我再试试。结贴先。。