如何禁用CToolBar工具栏中的某一按钮?
谢谢大家!

解决方案 »

  1.   

    有一个办法,比如你要把第一个按钮灰掉就
    m_wndToolBar.SetButtonInfo(0, 10000, TBBS_BUTTON, 0);
    只要把ID改成没有对应处理函数的就行
      

  2.   

    如何用VC++ 5.0实现工具栏及其属性的控制   任志民   VC++ 5.0风格的工具栏具有平面外观,左边带有一个“把手”,你可以通过鼠标拖动这个“把手”来移动工具栏。工具栏各组间带有分隔线(如图1所示)。当鼠标在工具栏上面移动时,工具栏上的相应按钮会突出显示。本文所讨论的增强型工具栏CEnhanceToolBar类由CToolBar类所派生,是CToolBar类的补充和扩展。     如果你并不在乎工具栏有没有“把手”的话,要生成平面工具栏是十分简单的。你只需要在CMainFrame的OnCreate()函数中添加一句话就可以(必须加在工具栏生成函数之后,因为MFC在生成工具栏时,要清除其式样):   //MainFrm.cpp   int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)   {    ......   if(!m_wndToolBar.Create(this)   //!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))    {    TRACE0("Failed to create toolbar\n");    return -1; // fail to create    }   m_wndToolBar.ModifyStyle(0,TBSTYLE_FLAT);   //设置工具栏为平面格式    ......   }   如果你的计算机安装了4.71.1712.3版本的COMCTL32.DLL(该动态库随IE 4.0一同发行),那就更好了,你的工具栏就会自动绘制分隔线。你可以通过鼠标拖动工具栏的非按钮区域来移动这种工具栏。GetRight中的工具栏就是这样的。   如果你要得到更好看(更“专业”)的工具栏,那么就请跟我一步步地做下去。      1.添加一个新类,本文中叫做CEnhanceToolBar类,由CToolBar类派生。   2.为CEnhanceToolBar类添加成员变量和函数的声明,并且根据你的需要设置其访问属性。   //EnhanceToolBar.h   // Overrides   // ClassWizard generated virtual function overrides   //{{AFX_VIRTUAL(CEnhanceToolBar)   //按钮状态变化时调用此函数   virtual void OnUpdateCmdUI(CFrameWnd*pTarget,BOOL bDisableIfNoHndler);   //}}AFX_VIRTUAL   // Implementation   public:    void DrawGrip(CWindowDC*pDC,CRect& rectWindow);//“把手”绘制函数    void EraseNonClient();//擦除非客户区    void DrawSpace();//分隔线绘制函数    void RedrawBackground();//背景重绘函数      private:    int ButtonNumber;//工具栏的按钮数(包括分隔线)    COLORREF HiLight, Shadow;//3D控件的加亮色和阴影色      3.添加成员函数的定义:   //EnhanceToolBar.cpp   void CenhanceToolBar :: OnUpdateCmdUI(CframeWnd * pTarget, BOOL bDisableIfNoHndler)   {//按钮状态变化时调用此函数    static CUIntArray Styles;    int Index;    UINT dwStyle;    for (Index = 0; Index < ButtonNumber; Index++)    {    dwStyle = GetButtonStyle(Index);    Styles.SetAtGrow(Index,dwStyle);//保存按钮的式样    }   CToolBar::OnUpdateCmdUI(pTarget,bDisableIfNoHndler);   //调用基类的处理函数    for (Index = 0; Index < ButtonNumber; Index++)    {//设置选中的按钮(checked button)为按下的状态    dwStyle = GetButtonStyle(Index);    if (dwStyle & TBBS_DISABLED)    return;//如果按钮为禁用状态,则返回(避免闪烁)    if (dwStyle & TBBS_CHECKBOX)    {    if (dwStyle & TBBS_CHECKED)    dwStyle |= TBBS_PRESSED;    else    dwStyle &= ~TBBS_PRESSED; //你可以设置灰色无效的风格   SetButtonStyle(Index,dwStyle);//设置按钮的式样 ,然后设置就是你想要的   }    }    //检查按钮的式样是否改变(按下或释放)    for (Index = 0; Index < ButtonNumber; Index++)    {    dwStyle = GetButtonStyle(Index);    if (Styles[Index] != dwStyle)    {    RedrawBackground();//重新绘制背景    Invalidate();//重新绘制整个工具栏    break;//已更新整个工具栏,因此没必要继续循环    }    }   }      void CEnhanceToolBar::DrawGrip(CWindowDC *pDC, CRect& rectWindow)   {//绘制把手    if (IsFloating())//如果工具栏是浮动状态,则不绘制“把手”    return;    CRect GripRect = rectWindow;//得到把手的矩形区域    GripRect.DeflateRect(1,1);//矩形区域的各边向中心靠近一个像素   if (m_dwStyle & CBRS_ORIENT_HORZ)   //如果工具栏为水平状态,则“把手”在左边    {    GripRect.right = GripRect.left + 3;//绘制第一条隆起的棱    pDC->Draw3dRect(GripRect, HiLight, Shadow);    GripRect.OffsetRect(4,0);//绘制第二条隆起的棱    pDC->Draw3dRect(GripRect, HiLight, Shadow);    }    else//如果工具栏为垂直状态,则“把手”在顶部    {    GripRect.bottom = GripRect.top + 3;//绘制第一条隆起的棱    pDC->Draw3dRect(GripRect, HiLight, Shadow);    GripRect.OffsetRect(0,4);//绘制第二条隆起的棱    pDC->Draw3dRect(GripRect, HiLight, Shadow);    }   }      void CEnhanceToolBar::DrawSpace()   {//绘制分隔线    CClientDC dc(this);    for (int Index = 0; Index < ButtonNumber; Index++)    {    UINT dwStyle = GetButtonStyle(Index);//获得按钮的类型    if (dwStyle & TBBS_SEPARATOR)//如果是分隔线    {    CRect rect;    GetItemRect(Index,rect);//获得矩形区域    if (m_dwStyle & CBRS_ORIENT_HORZ)    //工具栏为水平时分隔线为垂直    {    int w = rect.Width();    rect.DeflateRect((w-2)/2,0);//将矩形缩减为2~3个像素宽    dc.Draw3dRect(rect, Shadow, HiLight);//绘制分隔线    }    else//分隔线为水平    {    rect.left = rect.left - m_sizeButton.cx;    rect.right = rect.left + m_sizeButton.cx;    rect.top = rect.bottom+1;    rect.bottom = rect.top+3;    int h = rect.Height();    rect.DeflateRect(0,(h-2)/2);//将矩形缩减为2~3个像素高    dc.Draw3dRect(rect, Shadow, HiLight);//绘制分隔线    }    }    }   }    
      

  3.   

    void CEnhanceToolBar::EraseNonClient()   {//擦除非用户区    CWindowDC dc(this);    CRect rectClient;    GetClientRect(rectClient);    CRect rectWindow;    GetWindowRect(rectWindow);    ScreenToClient(rectWindow);    rectClient.OffsetRect(-rectWindow.left, -rectWindow.top);    dc.ExcludeClipRect(rectClient);       // 绘制非用户区的边界    rectWindow.OffsetRect(-rectWindow.left, -rectWindow.top);    DrawBorders(&dc, rectWindow);       // 擦除非绘制部分    dc.IntersectClipRect(rectWindow);    SendMessage(WM_ERASEBKGND, (WPARAM)dc.m_hDC);    DrawGrip(&dc, rectWindow); //绘制“把手”   }      由于平面工具栏是透明的,所以当改变尺寸和移动时(例如当拖动工具栏时),就需要重绘背景。同样,当按钮状态改变时(按下或释放)也需要进行这种操作。      void CEnhanceToolBar::RedrawBackground()   {//重新绘制背景    CWnd* pParent = GetParent();//获得父窗口指针    if (pParent)    {    CRect drawrect,rect;    GetWindowRect(&rect);//获得工具栏矩形区域    drawrect = rect;    pParent->ScreenToClient(&drawrect);//转换为父窗口坐标    pParent->InvalidateRect(&drawrect);//重绘矩形区域    //绘制父窗口的其他工具栏    for (CWnd* pSibling = pParent->GetWindow(GW_CHILD);pSibling;    pSibling = pSibling->GetNextWindow(GW_HWNDNEXT))    {    if (pSibling == this)    continue;    drawrect = rect;    pSibling->ScreenToClient(&drawrect);//兄弟窗口的坐标    pSibling->InvalidateRect(&drawrect);//重绘矩形区域    }    }   }      4.利用ClassWizard给CEnhanceToolBar类添加消息映射:   //EnhanceToolBar.h       //{{AFX_MSG(CEnhanceToolBar)    afx_msg void OnPaint();    afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp);    afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos);    //}}AFX_MSG      //EnhanceToolBar.cpp       BEGIN_MESSAGE_MAP(CEnhanceToolBar, CToolBar)    //{{AFX_MSG_MAP(CEnhanceToolBar)    ON_WM_PAINT()    ON_WM_NCCALCSIZE()    ON_WM_WINDOWPOSCHANGING()    //}}AFX_MSG_MAP    END_MESSAGE_MAP()      5.为消息映射函数添代码:   void CEnhanceToolBar::OnPaint()   {    CToolBar::OnPaint();//绘制标准工具栏    EraseNonClient();//擦除背景    DrawSpace();//绘制立体分隔线   }   void CEnhanceToolBar::OnNcCalcSize(BOOL bCalcValidRects,    NCCALCSIZE_PARAMS FAR* lpncsp)   {// 计算非用户区域,用于调整“把手”    CToolBar::OnNcCalcSize(bCalcValidRects,lpncsp);    if (IsFloating())//如果工具栏是浮动状态,则不绘制“把手”    return;   if (m_dwStyle & CBRS_ORIENT_HORZ)   //如果工具栏为水平状态,则“把手”在左边    {    lpncsp->rgrc[0].left += 2;    lpncsp->rgrc[0].right += 2;    }    else//如果工具栏为垂直状态,则“把手”在顶部    {    lpncsp->rgrc[0].top += 4;    lpncsp->rgrc[0].bottom += 4;    }   }      void CEnhanceToolBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)   {//当尺寸、位置或Z方向次序变化时,程序框架调用此成员函数    CToolBar::OnWindowPosChanging(lpwndpos);    RedrawBackground();//重新绘制背景   }      6.编写构造函数,加入下面的代码:   CEnhanceToolBar::CEnhanceToolBar()   {    HiLight = ::GetSysColor(COLOR_3DHILIGHT);//获得3D控件的加亮色    Shadow = ::GetSysColor(COLOR_3DSHADOW);//获得3D控件的阴影色   ButtonNumber = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);   //获得工具栏的按钮数(包括分隔线)   }   把以上程序编译运行后,很酷的工具栏就会出现了。下面是几点说明:   (1)关于工具栏的其他格式请参考COMMCRTL.H。   #define TBSTYLE_TOOLTIPS 0x0100   #define TBSTYLE_WRAPABLE 0x0200   #define TBSTYLE_ALTDRAG 0x0400   #define TBSTYLE_FLAT 0x0800......      (2)如果你的计算机安装了4.71.1712.3版本的COMCTL32.DLL(随IE 4.0一同发行),那么你不需要添加下列的函数,这样就会更简单。   void DrawSpace();//分隔线绘制函数   void RedrawBackground();//背景重绘函数   virtual void OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler);   void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos); 
      (3)如何在工具栏的按钮中间加入一个分隔线呢?很简单,使用资源编辑器打开应用程序的工具栏,拖动一个按钮,使其与上一个按钮离开一定距离,松开鼠标键就可以了。