程序有多个视图,不同视图有不同工具栏,并且因为设计上的原因,这些工具栏到底都是些什么没法一口气确定。总之,现在没法在创建MDI子窗口或窗口之时,就创建工具栏,或者说,不能在OnCreate函数或OnInitialUpdate函数或OnInitDialog函数中加创建工具栏的代码;而只能在用户点了某个菜单之后,再创建工具栏。
创建工具栏并不困难,但奇怪的是,那些工具栏上的按钮都是不可用的。已经建立好消息映射,也尝试过在WM_UPDATE_COMMAND_UI中加代码,但都无效。
怎么回事?
如果我有说得不清楚的,可以指明,我会不停上来看,做补充。

解决方案 »

  1.   

    在某个类中如是写:
    // parent 这个工具栏的父窗口
    CToolBar * CBinBmpViewer::getToolBar(CWnd * parent)
    {
    if (!floatBar) { //这个floatBar就是要动态创建的工具栏
    floatBar = new CToolBar;
    if (!floatBar->CreateEx(parent, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_LEFT
    | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
    !floatBar->LoadToolBar(IDR_TBAR_BINBMP)) {
    delete floatBar;
    return NULL;
    }
    }
    return floatBar;
    }
    我的程序叫ImageProcessor,因此有个CImageProcessorView类,其中有如是代码:
    activeBar = activeView->getToolBar(GetParent());
    CMDIChildWnd * parent = (CMDIChildWnd *)GetParent();
    parent->EnableDocking(CBRS_ALIGN_ANY);
    activeBar->EnableDocking(CBRS_ALIGN_LEFT | CBRS_ALIGN_RIGHT);
    parent->DockControlBar(activeBar);
    activeBar->ShowWindow(SW_SHOW);
    这个activeView就是上面代码提到的CBinBmpViewer的一个对象,从中得到一个工具栏,然后在MDI子窗口的视图类里加一个新的工具栏。因为CMDIChildWnd是CFormView的父窗口,所以getToolBar的参数用了GetParent()来得到当前的CMDIChildWnd对象。
      

  2.   

    这些代码看起来都没有问题,应该是ON_UPDATE_COMMAND_UI没有响应对,要在响应函数中调用pCmdUI->Enable(),另外注意一下你的响应函数是否被调用了。
      

  3.   

    这些函数都调到了,但是ON_UPDATE_COMMAND_UI没有响应。CBinBmpViewer继承自CDialog类,为此我加了个函数如下:
    void CSubView::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu)

    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;
    }
    }
    这个函数是抄来的,并且加了之后,菜单响应ON_UPDATE_COMMAND_UI了。但是工具栏不行。怎么办呢?
    或者从另一个方面来想,为什么我为工具栏加了消息响应函数了却是灰的呢?
      

  4.   

    ON_UPDATE_COMMAND_UI是加在哪个类里面?映射宏和响应函数分别是怎么写的?
      

  5.   

    不好意思上午去上课了。
    CBinBmpViewer类是这个问题的主角,这个类继承自CDialog,加过上面的OnInitMenuPopup函数之后,它上面的菜单是可以复选了,所以这个函数是工作的。
    消息映射中有如下代码:
    ON_COMMAND(ID_SUBVIEW_POPMENU_OTSU, OnSubviewPopmenuOTSU)
    ON_COMMAND(ID_SUBVIEW_POPMENU_ENTROPY, OnSubviewPopmenuEntropy)
    ON_UPDATE_COMMAND_UI(ID_SUBVIEW_POPMENU_OTSU, OnUpdateSubviewPopmenuOTSU)
    ON_UPDATE_COMMAND_UI(ID_SUBVIEW_POPMENU_ENTROPY, OnUpdateSubviewPopmenuEntropy)
    这两个ID就是工具栏上的按钮。在加好资源画好按钮后,加了如上代码与相关消息函数的实现。这些实现函数里就放了个AfxMessageBox函数来弹个框检验。
    到这步觉得消息映射应该是加好了,然后再在这个类里加了如上给出的getToolBar函数,动态加载这个工具栏。最后在主视图类里调用它。这些已经给出。
    现在已经可以看到getToolBar这个函数只在第一次调用它时生成工具栏,在类的析构函数里删除。其它时间都是只显示与隐藏。
    这些工具栏没有对应的菜单项。原本以为和这个有关系,但加了隐藏的菜单也不行,是不是不得不显示它才好?
      

  6.   

    突然明白是怎么回事了……
    在创建工具栏时,指定它的父窗口是MDI子窗口,而在写消息映射时,却是写在这个对话框里……
    这个要怎么办呢?我想让这个工具栏停靠在子窗口里,这样就不得不认其为父,但又不想把消息处理函数写在MDI子窗口里,这样会破坏程序的结构与封装性……
    如何改变这家伙的消息投递方法,让它不是将消息发给父窗口而是给某个指定的窗口呢?