Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CGSToolBar

0.00/5 (No votes)
20 Feb 2001 1  
A flexible extension to the CToolBar class
  • Download source files - 29 Kb
  • Download demo executable - 11 Kb
  • Sample Image - CGSToolBar.gif

    Introduction

    During my current project, I found myself in possession of a number of toolbars. It's a paint program, so it started to be quite painful, having various toolbars over parts of the image, and half of the real estate is just wasted room (i.e. the caption bar ). I decided to try and write a class derived from CToolBar that was tricked into thinking it was docked when it wasn't, so it drew with a gripper and no caption bar. Simple, right?

    Well, in the end, I posted a question here, and got an answer from Masoud, who was trying to do the same thing. He found the answer, and along the way we bounced ideas off each other and ended up with a useful toolbar class that we thought was worth sharing. Please direct all compliments to me, any bugs are his fault ( only kidding Masoud ;0)

    To use CGSToolBar, just include the header file in your CMainFrame header, and replace toolbar resources with CGSToolBar. For the auto menus, you also need to create three resource ID's, namely ID_MENU_GRADIENT, ID_MENU_CAPTION, and ID_MENU_BUTTONS. More on those later.

    The header file for CGSToolBar lists the following extra functions:

    // Function to dock bars next to one another (used typically on startup)
    
    void DockBarNextTo(CControlBar* pDockedBar, UINT nDockBarID = 0); 
    
    // Self Explanatory
    
    bool IsBarVisible() { return ((this->GetStyle() & WS_VISIBLE) !=0); }; 
    
    // Three functions to change the contents of a button
    
    // First one takes a pointer to a bitmap and a 0 based position 
    
    void OnChangeButton(CBitmap * pButton, int Position); 
    // Second used a resource ID, position, and transparent colour. 
    
    // Transparency does not work with gradient, this is the fault of the gradient code 
    
    void OnChangeButton(int BitmapID, int Position,COLORREF Transp = RGB(255,0,255)); 
    // Last one changes to a solid colour ( remember this was for a paint program ;0) 
    
    void OnChangeButton(COLORREF colour, int Position);
    
    // Sets a button to have a drop down arrow next to it. 
    
    // See code for further instructions on how to use this, or the MSDN 
    
    void SetDropdown(int Position); 
    
    // Push buttn mode means the last button pushed stays 'down', useful for example 
    
    // if toolbar selects different 'modes' 
    
    // First function sets global behaviour 
    
    void SetPushButton (bool push); 
    // Second allows you to specific individual buttons to group together this way. 
    
    void SetPushButton (bool push, int nPos); 
    
    // The core function - this turns the caption bar off and on 
    
    // When it is off, the floated toolbar has a gripper and resizes slightly to allow dragging 
    
    void SetShowCaption (bool caption); 
    
    // This just calls SetWindowText, but I put it in just in case anyone didn't realise that is how to do it 
    
    
    void SetCaption (CString caption); 
    
    // Sets the colours for the gradient 
    
    void SetBackground(COLORREF col1, COLORREF col2) { m_RGB1 = col1; m_RGB2 = col2; }; 
    
    // The gradient is drawn in OnEraseBackground - a solid colour or bitmap could just as easily be used. 
    
    void SetUseGradient(bool grad) { m_bUseGradient = grad; }; 
    // This allows you to pass in a menu to be shown as a context menu 
    
    void SetMenu(int ID) { m_iMenuID = ID; }; 
    // These four turn on the extra menu items available, to allow the user to turn on and off pushbuttons, the caption bar and the gradient fill 
    
    void SetMenuAll(bool menu); 
    void SetMenuPushbutton (bool bPush); 
    void SetMenuCaption (bool bCaption); void SetMenuGradient (bool bGradient); 
    
    // Fairly obvious stuff 
    
    bool GetShowCaption() { return m_bShowCaption; }; 
    bool GetUseGradient() { return m_bUseGradient; }; 
    bool GetPushbutton() { return m_bPushButton; };

    There are a few items of particular interest.

    The OnChangeButton method which uses a resource also displays the bitmap transparently. It does this by generating a 1 bit alpha mask, that is, a bitmap that is white where it should draw, and black where it should not. There are other, more generic examples of how to do colour keyed transparency using this method in the appropriate section of CodeProject. Windows has a TransparentBlt function, but it is not supported in Windows 95, so you're better not to use it.

    The SetMenu allows you to pass in the ID of any menu and it will be used as a context menu, BUT by using the other SetMenu methods listed, you can also get CGSToolBar to give you these extra options to your menu. For exmaple, I pass in a menu that lists all my toolbars, so I get MSDev type behaviour where a right click lets me turn toolbars off and on, but at the top I let my users choose if they want caption bars or not.

    SetDropDown allows you to set up a button to display a menu when you push the arrow provided, but there is work to be done in CMainFrame to make this happen. Basically you need to catch TBN_DROPDOWN in OnNotify, and then figure out which toolbar was pressed and show/handle the appropriate menu. If you only have one toolbar you can override OnDropDown directly. You can get a menu to return the selection value to you by passing TPM_RETURNCMD to TrackPopupMenu and grabbing the returning DWORD, which you can then switch. There are other tutorials here on how to do this, and it's not the focus of this article to reiterate them. This behaviour is not shown in the demo project.

    Probably the trickiest thing we had to do was get the toolbar outline the correct size when drawing. It turns out that although MSDN is silent on the issue, this is done by an object in the toolbar of type CDockContext, called m_pDockContext. It keeps track of four LPRECT structures, and we update them by firing a timer when we push the left mouse button. We need to change it both when it is not docked, and when it is docked, so that it always appears the correct size. When I say always, I have not found a way to change this rect initially, as I could not override the class successfully and replace the object in CGSToolBar with one of our own, and the RECT's are set in the BeginDragging method. The end result is you get an incorrect rect drawn when you click, but it's correct as you move, and snaps to the outline you were dragging when finished.

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here