看到一些软件,如果工具条上的按钮太多,就在最右边显示一个下拉式的菜单,里面包含有没有被显示出的工具按钮?我知道用ReBar,但我却实现不了,哪位老兄能给出一段参考源码???拜托了!!!

解决方案 »

  1.   

    http://www.codeproject.com/docking/
    有n多例子,看了别忘了分..........
      

  2.   

    //Chev.h
    #if !defined(AFX_CHEVBAR_H__ADA7D7F6_E2C1_11D3_84C7_0080450EA020__INCLUDED_)
    #define AFX_CHEVBAR_H__ADA7D7F6_E2C1_11D3_84C7_0080450EA020__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000#define _WIN32_IE 0x0500
    #define RBBS_USECHEVRON 0x00000200 
    #define RBN_CHEVRONPUSHED (RBN_FIRST - 10)
    typedef struct tagNMREBARCHEVRON
    {
        NMHDR hdr;
        UINT uBand;
        UINT wID;
        LPARAM lParam;
        RECT rc;
        LPARAM lParamNM;} NMREBARCHEVRON, *LPNMREBARCHEVRON;class CChevBar : public CReBar
    {
    public:
    CChevBar();public: //{{AFX_VIRTUAL(CChevBar)
    //}}AFX_VIRTUALpublic:
    virtual ~CChevBar();protected:
    //{{AFX_MSG(CChevBar)
    //}}AFX_MSG /*
    Reflection handler for the Chevron push
    */
    void OnChevronPushed( NMHDR * pNotifyStruct, LRESULT* result ); DECLARE_MESSAGE_MAP()
    };///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}#endif // !defined(AFX_CHEVBAR_H__ADA7D7F6_E2C1_11D3_84C7_0080450EA020__INCLUDED_)
    //
    //Chev.cpp
    #include "stdafx.h"
    #include "Chev.h"
    #include "ChevBar.h"
    #include "ToolMenu.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/*
    Usage:
    if (!m_wndReBar.AddBar(&m_wndToolBar, NULL, NULL, RBBS_USECHEVRON))
    return -1;
    REBARBANDINFO rbbi;

    CSize sizeBar;
    m_wndToolBar.GetToolBarCtrl().GetMaxSize (&sizeBar);

    rbbi.cbSize = sizeof(rbbi);
    rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_IDEALSIZE | RBBIM_SIZE | RBBIM_ID;
    rbbi.cxMinChild = 0;
    rbbi.cyMinChild = sizeBar.cy;
    rbbi.cx = rbbi.cxIdeal = sizeBar.cx;
    rbbi.wID = 0;

    m_wndReBar.GetReBarCtrl().SetBandInfo(0, &rbbi); 

    */
    /////////////////////////////////////////////////////////////////////////////
    // CChevBarCChevBar::CChevBar()
    {
    }CChevBar::~CChevBar()
    {
    }
    BEGIN_MESSAGE_MAP(CChevBar, CReBar)
    //{{AFX_MSG_MAP(CChevBar)
    //}}AFX_MSG_MAP // Reflection message entry for Chevron push
    ON_NOTIFY_REFLECT( RBN_CHEVRONPUSHED, OnChevronPushed )
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CChevBar
    /*
    This is the handler when a chevron is pushed.
    */
    void CChevBar::OnChevronPushed( NMHDR * pNotifyStruct, LRESULT* result )
    {
    NMREBARCHEVRON* pChev = (NMREBARCHEVRON*) pNotifyStruct;
    // Has the band of the chevron that generated this message
    int iBand = pChev->uBand; // Have to get the child window handle this band holds
    REBARBANDINFO rbinfo;
    rbinfo.cbSize = sizeof(rbinfo);
    rbinfo.fMask = RBBIM_CHILD;
    GetReBarCtrl().GetBandInfo ( iBand, &rbinfo ); // Check if the child window is a toolbar
    // Some rebar bands may have other windows, so that is left as an exercise
    // to the user :-)
    CToolBar *pTBar = (CToolBar *)CToolBar::FromHandle ( rbinfo.hwndChild );
    ASSERT(pTBar);
    ASSERT(pTBar->IsKindOf(RUNTIME_CLASS(CToolBar))); // Create a popup menu to show hidden buttons
    CToolMenu pop;
    pop.CreatePopupMenu (); // The CToolMenu uses the toolbar pointer to get associated text and image
    // information. If there is a better way please do so.
    // This menu was created with local scope, hence the temp pointer
    // pTBar can be stored i guess...
    pop.m_pToolbar = pTBar; // We have to determine the hidden buttons
    /*
    1. Obtain band rectangle (subtract chevron width if you want to)
    2. Get the button rectangle
    3. Check if the intersecting rectangle is same as the button rectangle
    4. If they intersect then the button is shown
    */ // Get band rectangle.
    CRect rectBand;
    GetReBarCtrl ().GetRect( iBand, &rectBand );
    rectBand.right = rectBand.Width ();
    rectBand.left  = 0 ;

    // It depends on the user to decide if this subtraction is necessary, if they feel
    // happy about the chevron hiding a part of a button then remove this code
    CRect rectChevron;
    rectChevron = pChev->rc;
    rectBand.right -= rectChevron.Width (); // Screen co-ordinates for Menu to be displayed
    CPoint ptMenu;
    ptMenu.x = rectChevron.left;
    ptMenu.y = rectChevron.bottom;
    ClientToScreen ( &ptMenu ); // This flag indicates if atleast one has been added to the menu
    // POPUP Menu is shown only if atleast one item has to be shown
    BOOL bAtleastOne=FALSE;
    int iCount, iButtonCount = pTBar->GetToolBarCtrl().GetButtonCount();
    for ( iCount = 0 ; iCount < iButtonCount ; iCount++ )
    {
    // Get the id of the toolbar button
    int id = pTBar->GetItemID( iCount );

    // If the button is a separator then we can also add a separator to the
    // popup menu
    if (  pTBar->GetButtonStyle ( iCount ) & TBSTYLE_SEP )
    {
    // It wouldnt be nice if there is a separator as the first item in the menu
    if ( bAtleastOne )
    pop.AppendMenu ( MF_SEPARATOR );
    }
    else
    {
    // Get the button rectangle
    CRect rectButton;
    pTBar->GetItemRect ( iCount, &rectButton ); // Check the intersection of the button and the band
    CRect interRect;
    interRect.IntersectRect ( &rectButton, &rectBand ); // if the intersection is not the same as button then
    // the button is not completely visible, so add to menu
    if ( interRect != rectButton )
    { UINT iMenuStyle = MF_OWNERDRAW;

    // Have to reflect the state of the menu item, so check the state of the 
    // button and enable or disable the items
    if ( pTBar->GetToolBarCtrl().IsButtonEnabled ( id ) )
    iMenuStyle |= MF_ENABLED;
    else
    iMenuStyle |= MF_DISABLED; // Add the item to the menu with the id of the toolbar button
    // This id is used to notify the parent if the user selects that item
    pop.AppendMenu ( iMenuStyle, id ); // Yeah, have added one, so can show the menu
    bAtleastOne=TRUE;
    }
    }
    } // Show the menu if atleast one item has been added
    if ( bAtleastOne )
    pop.TrackPopupMenu ( TPM_LEFTALIGN|TPM_TOPALIGN, ptMenu.x, ptMenu.y, this ); // Delete our menu
    pop.DestroyMenu ();
    }
      

  3.   

    //ToolMenu.h
    #if !defined(AFX_TOOLMENU_H__E8777520_DE4C_11D3_84C7_0080450EA020__INCLUDED_)
    #define AFX_TOOLMENU_H__E8777520_DE4C_11D3_84C7_0080450EA020__INCLUDED_#if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000/////////////////////////////////////////////////////////////////////////////
    /*
    This is our custom owner drawn menu that shows the hidden tool bar buttons
    with optional text
    */
    class CToolMenu : public CMenu
    {
    public:
    CToolMenu(); // The toolbar from which the bitmaps/icons have to be extracted
    CToolBar* m_pToolbar; // Overridables
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);public:
    virtual ~CToolMenu();
    };///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}#endif // !defined(AFX_TOOLMENU_H__E8777520_DE4C_11D3_84C7_0080450EA020__INCLUDED_)//ToolMenu.cpp
    #include "stdafx.h"
    #include "ToolMenu.h"
    #include "afxpriv.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CToolMenu
    /*
    Toooooo lazy to calculate or to obtain from the system
    */
    #define MENU_SPACETEXT 10
    #define MENU_TOPFACTORS 2
    #define MENU_LEFTFACTORS 4
    #define MENU_RIGHTFACTORS 4
    #define MENU_BOTTOMFACTORS 2
    #define MENU_MAXWIDTH 100CToolMenu::CToolMenu()
    {
    }CToolMenu::~CToolMenu()
    {
    }/////////////////////////////////////////////////////////////////////////////
    /*
    This is the drawing routine for the owner drawn menu
    The toolbar pointer have to be valid ! 
    */
    void CToolMenu::DrawItem( LPDRAWITEMSTRUCT lpds ) 
    { // If toolbar not set then you cannot proceed drawing so just skip
    if ( !m_pToolbar )
    return; // Get the image list, gotta do this because i have to draw the bitmap
    CImageList * pImgList = m_pToolbar->GetToolBarCtrl().GetImageList();
    ASSERT( pImgList ); // Get the size of the image
    int cx, cy, iIndex, iImage;
    UINT iID, iStyle;
    ::ImageList_GetIconSize(*pImgList, &cx, &cy); // Have to find which image the button is using, image list wants index
    iID = lpds->itemID;
    iIndex = m_pToolbar->CommandToIndex ( iID );
    m_pToolbar->GetButtonInfo ( iIndex, iID, iStyle, iImage ); CDC dc;
    dc.Attach ( lpds->hDC ); // Get the drawing rectangle
    CRect rectDraw = lpds->rcItem;

    // Refer DrawIndirect( ) API for the drawstyle, raster op, etc...
    // Only selection/checked/grayed state is handled here
    // Add or change here for all the drawing operations...
    int iRasterOP = SRCCOPY;
    int iDrawStyle= ILD_NORMAL; COLORREF clrTextBack;
    COLORREF clrTextFore;
    COLORREF clrMaskFore; clrTextBack = ::GetSysColor (COLOR_MENU);
    clrTextFore = ::GetSysColor (COLOR_MENUTEXT);

    clrMaskFore = CLR_DEFAULT; // Get appropriate colors from the system for painting our menu
    if ((lpds->itemState & ODS_SELECTED) &&
    (lpds->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
    {
    clrTextBack = ::GetSysColor (COLOR_HIGHLIGHT);
    }
    dc.FillSolidRect ( rectDraw, clrTextBack ); if (lpds->itemState & ODS_GRAYED || lpds->itemState & ODS_DISABLED )
    {
    clrTextFore = ::GetSysColor (COLOR_GRAYTEXT);
    iDrawStyle= ILD_BLEND25;
    clrMaskFore = CLR_NONE;
    }
    CPoint lefttop;
    lefttop.x = rectDraw.left + MENU_LEFTFACTORS;
    lefttop.y = rectDraw.top + MENU_TOPFACTORS ; // A  special 3d rect for the checked state
    if (lpds->itemState & ODS_CHECKED )
    {
    clrTextFore = ::GetSysColor (COLOR_3DHILIGHT); CRect rect3D;
    rect3D.SetRect ( lefttop.x, lefttop.y, lefttop.x+cx, lefttop.y+cy );
    rect3D.InflateRect (2,2);
    dc.Draw3dRect( &rect3D, RGB(0,0,0), clrTextFore );
    } // Draw the toolbar button bitmap
    pImgList->DrawIndirect( &dc, iImage, lefttop, CSize(cx, cy), CPoint(0, 0), 
    iDrawStyle, iRasterOP, clrTextBack, clrMaskFore); // Now time to draw the text
    CRect rectText = rectDraw;
    rectText.DeflateRect ( MENU_SPACETEXT + MENU_LEFTFACTORS + cx, MENU_TOPFACTORS, MENU_RIGHTFACTORS, MENU_BOTTOMFACTORS ); COLORREF clrTextForeold = dc.SetTextColor( clrTextFore );
    dc.SetBkMode ( TRANSPARENT );
    // Try to load the string from resource
    // The resource of the toolbar buttons usually have the format
    // Status bar text\ntooltip
    // this extracts the tooltip text and displays
    // Users who dont like this, please change whatever you wanted to display
    CString strText;
    if ( strText.LoadString ( iID ) )
    {
    int iPos = strText.Find ( '\n', 0 );
    if ( iPos != -1 )
    {
    CString strTemp = strText.Mid( iPos+1 );
    dc.DrawText ( strTemp, -1, &rectText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS );
    }
    } dc.SetTextColor( clrTextForeold ); // Detach the dc
    dc.Detach ();
    }void CToolMenu::MeasureItem( LPMEASUREITEMSTRUCT lpms ) 
    {
    // no tool bar, then no op
    if ( !m_pToolbar )
    return; // Get imagelist
    CImageList * pImgList = m_pToolbar->GetToolBarCtrl().GetImageList();
    ASSERT( pImgList ); // get image size
    int cx, cy;
    ::ImageList_GetIconSize(*pImgList, &cx, &cy); // Calculate width and height of the item.
    // To lazy to get the info from system or to calculate.
    lpms->itemHeight = cy + MENU_BOTTOMFACTORS + MENU_TOPFACTORS;
    lpms->itemWidth = cx + MENU_LEFTFACTORS + MENU_RIGHTFACTORS + 
    MENU_MAXWIDTH + MENU_SPACETEXT;
    }
    用法我写在
    上条回复的Usage里面了!
    这也是我下载的代码,只不过整理了一下而已!:)还有在MSDN中有篇标题为
    Creating an Internet Explorer-style Toolbar
    的文章也详细的讲解了Chevron的的用法!