65.9K
CodeProject is changing. Read more.
Home

Custom Draw Buttons & A Smarter Groupbox

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (10 votes)

Jan 12, 2000

viewsIcon

208381

downloadIcon

5635

A class to make working with radio buttons easier, and another for custom drawing buttons

  • Download demo project - 66 Kb
  • Sample Image - CustomButtons.gif

    Part 1. CRadioGroup: A group box class that handles radio buttons as an array

    Sometimes when you have a number of radio buttons in a group you don't want to deal with them individually. CRadioGroup is a simple class that allows you to access any radios bounded by a groupbox as a 1 based array.

    Class hierarchy:

    CObject 
       | 
       +-CCmdTarget 
             | 
             +-CWnd 
                 | 
                 +-CButton 
                      | 
                      +-CRadioGroup
    

    How do you use the CRadioGroup?

    To use the CRadioGroup class simply subclass a Groupbox in a dialog and use the SetRadio() and GetRadio() methods to access the currently selected radio button. I have made the accessing 1 based ( 0 based arrays have always upset me), but this can be easily changed.

    When used in conjunction with CCustomButton the CRadioGroup will also receive a BN_CLICKED message whenever a contained radio is clicked. Thus only one handler is required for any number of radio buttons inside a group box.

    Subclassing the groupbox:

    void CMyDialog::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CCRadioGroupSampleDlg)
    	DDX_Control(pDX, IDC_GROUP1, m_Group1);
    	//}}AFX_DATA_MAP
    }
    

    Handling hits on the radio buttons via the groupbox (NB. The radio buttons must be CCustomButton's or derived from a CCustomButton) :
     

    ON_BN_CLICKED(IDC_GROUP1, OnGroup1)

    The code for CRadioGroup is in CRadioGroup.cpp/.h (See source.)
     

    How does the CRadioGroup work?

    The class simply step through the auto-radio buttons that are bounded by it and finds the currently selected one. If this is the second auto-radio button then GetRadio() will return 1. Conversely SetRadio(1) will select this one, deselecting the currently selected one. Simple.

    Part 2. CCustomButton: Generic user draw buttons

    When I started writing MFC dialog code I thought it would be easy to override the drawing of buttons. Foolish me!

    All I wanted was to draw the buttons based on the type and current state while retaining the button behaviour. After some trial and error I created a class that allowed standard button behaviour but with the option of the user handling all drawing. I have also added some extra features including

    • A user defined hit region
    • Support for hovering behavior
    • Simple animation

    Class hierarchy:

    CObject
       | 
       +-CCmdTarget 
             | 
             +-CWnd 
                 | 
                 +-CButton
                      |
                      +-CCustomButton
    

    Sample Code:

    I have included a range of sample implementations of custom buttons. These are all derived from CCustomButton and are displayed in the smaple code provided.

    • CCustomIconButton - Button that displays a centered icon taken from a toolbar style strip bitmap and also supports simple hovering effects
    • CCustomTextButton - Button that displays colored text
    • CAnimatingButton - Button that displays animated colored text
    • CRoundButton - A round button that supports hovering effects. The code for drawing the round buttons was written by Chris Maunder (Copyright (c) 1998.).

    How to use CCustomButton:

    1. Subclass your button with a class derived from CCustomButton.
    2. To draw your own button, simply override the following 2 methods :
      virtual bool CustomDraw() const {return true;}
      virtual void OnDraw(CDC*,const CCustomButtonData& state)
      {
      	//Draw the button based on state flags in parameter 'state'
      }
      
    3. To provide hovering effects override the following 2 methods :
      virtual bool    HoverEffects()const{return true;}
      
      virtual void    OnHover(bool bEnteringButton)
      {
      	// Override OnHover() to provide non-drawing effect such as sounds.
      	// Any drawing effects while hovering can be added in OnDraw()
      }
      
    4. To provide simple animation call SetAnimation().

      void    SetAnimation(bool bActive,int nNoOfFrames=0, int nMillisecsPerFrame=10);
      //If set active OnDraw() will be called every 'nMillisecsPerFrame' with 
      //the frame variable 'CCustomButtonState::m_nFrame' incremented each time.
      

    For more information, please refer to the comments in the source code.