Click here to Skip to main content
11,720,785 members (83,676 online)
Click here to Skip to main content

FooButton

, 7 Oct 2006 CPOL 450.2K 13.9K 227
Rate this:
Please Sign up or sign in to vote.
A lightweight general-purpose owner drawn bitmap button.

Introduction

This article describes FooButton, a lightweight owner-drawn button class that's served me well for several years.  Although there are plenty of other excellent button classes at CodeProject, I thought I'd add this trusty friend to the pile in the hope that someone may find it equally useful.

Features

FooButton lets you use a vanilla CButton as a:
  • standard pushbutton
  • pushbutton button with a drop-down indicator
  • multi pushbutton (like IE's "Back" and "Next" buttons)
  • checkbutton
  • hyperlink
  • static text control that's responsive to mouse clicks
  • check box
  • radio button
Support is also provided for:
  • bitmaps (currently only 16-color)
  • left-justified, centered and multi-line captions
  • colored captions
  • gradient shaded button backgrounds
  • popup menus
  • hot tracking
  • optional focus rectangle and "default button" indicator
  • grouped checkbuttons

How to use FooButton

  1. First, associate a standard button control (eg: IDC_FOO_BUTTON) in your dialog with an instance of the object.

      /////////////
      // MyDialog.h
      #include "FooButton.h"
      ...
      FooButton m_fooButton;
    ///////////////
    // MyDialog.cpp
    void CMyDialog::DoDataExchange(CDataExchange* pDX)
    {
      CDialog::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CMyDialog)
      DDX_Control(pDX, IDC_FOO_BUTTON, m_fooButton);
      //}}AFX_DATA_MAP
    }
    

  2. Then, initialize the instance in your dialog's OnInitDialog() method to suit your needs.  In this example, the button is set to display a bitmap and a drop-down indicator.

    // Initialize FooButton
    m_fooButton.setBitmapId (IDB_FOO_BUTTON);
    m_fooButton.setType (FooButton::Type::pushButtonDropDown);
    
         Drop-down pushbutton

API

 Method Purpose
 getType(), setType() Gets and sets the button's type 
 getTextStyle(), setTextStyle() Gets and sets the button's text style 
 getTextColor(), setTextColor() Gets and sets the button's text color 
 getFocusStyle(), setFocusStyle() Gets and sets the button's focus style 
 getGradient(), setGradient() Gets and sets the button's gradient property 
 getBitmapId(), setBitmapId() Gets and sets the button's (optional) bitmap id 
 displayPopupMenu() Displays a popup menu below the button 
 isChecked(), check() Gets and sets a checkButton's checked state 
 isMultiClicked(), clearMultiClick() Gets and resets a multiPushButton's multi-clicked state 
 addToGroup(), removeFromGroup() Adds/removes a checkButton to/from a button group 
 reset() Frees storage used by all button groups 
 

Using FooButton as a check button

You can freely change any property of the button at run time.  This code snippet turns the button into a checkbutton and checks it.  Use check() and isChecked() to set and retrieve the button's checked state.

// Make it a checkbutton and check it
m_fooButton.setType (FooButton::Type::checkButton);
m_fooButton.check (true);
ASSERT (m_fooButton.isChecked());    // testing
     Unchecked   Checked

Gradient shading

Pushbuttons and checkbuttons can be set to display a gradient shaded background by calling setGradient().  This method has no effect if the button isn't a pushbutton or checkbutton.

// Use a gradient shaded background
m_fooButton.setGradient (true);
     Using a gradient shaded background

Button groups

You can make a bunch of checkButtons behave as mutually exclusive radio buttons by adding them to a button group.  A button group is just a named collection of buttons.  FooButton automatically handles group creation, membership and cleanup.

// Make "size" checkbuttons mutually exclusive
m_btnSmall.addToGroup (_T("foo"));
m_btnMedium.addToGroup (_T("foo"));
m_btnLarge.addToGroup (_T("foo"));
m_btnXLarge.addToGroup (_T("foo"));
     A button group

Displaying a popup menu

To display a popup menu in response to a button click, call displayPopupMenu().  You can call this method for any type of FooButton.

void CMyDialog::OnFooButton()
{
  CMenu menu;
  menu.LoadMenu (IDR_POPUP_MENU);
  CMenu* pPopupMenu = menu.GetSubMenu (0);
  int nResult = m_fooButton.displayPopupMenu (pPopupMenu);
  if (0 != nResult)
     PostMessage (WM_COMMAND, nResult);
}
     Normal   Pressed

Multi-pushbuttons

A multi-pushbutton behaves as two buttons in one, similar to IE's "Back" and "Next" buttons.  When the user clicks the button's drop-down region, FooButton sets its "multi-clicked" property to true.  You can query this property by calling isMultiClicked().  Regardless of whether the user clicked in the button's main or drop-down region, a standard notification is sent to the parent.  To clear the button's multi-click property, call clearMultiClick().

void CMyDialog::OnFooButton()
{
  if (m_fooButton.isMultiClicked()) {

      // Display menu if drop-down region was clicked
      CMenu menu;
      menu.LoadMenu (IDR_POPUP_MENU);
      CMenu* pPopupMenu = menu.GetSubMenu (0);
      int nResult = m_fooButton.displayPopupMenu (pPopupMenu);
      if (0 != nResult)
         PostMessage (WM_COMMAND, nResult);

      // Remember to clear the button's multi-click property!
      m_fooButton.clearMultiClick();

  } else {

      // Otherwise do default action
      PostMessage (WM_COMMAND, IDC_DEFAULT_ACTION);
  }
}
     Multi-pushbutton   Multi-pushbutton with drop-down pressed

Check boxes and radio buttons

You can make a FooButton appear as a standard check box or radio button by using the FooButton:Type::checkBox and FooButton:Type::radio types.  Of course, this is really only useful when you want to also display a bitmap or add menu support to the button.

// Appear as check box and radio button
m_fooButton1.setType (FooButton::Type::checkBox);
m_fooButton2.setType (FooButton::Type::radio);
     Check box   Radio button with a popup menu

Hyperlink button

A hyperlink button is just a regular button that renders itself as a hyperlink.  You can navigate to a URL or perform any other action in the button's handler.

// Appear as hyperlink
m_fooButton.setType (FooButton::Type::hyperink);
     A button that looks like a hyperlink

Text color

You can change the color of the button's text at any time by calling setTextColor().  The text of hyperlink buttons is always rendered in C_HyperlinkColor and that of disabled buttons is always rendered in the standard etched format.

// Draw caption in red
m_fooButton.setTextColor (RGB (192, 0, 0));
     Custom caption text color

Focus rectangle

By default, a FooButton doesn't display a focus rectangle.  Call setFocusStyle() with FooButton::Focus::normalFocus to enable the button to display a focus rectangle.

// Allow focus rectangle to be displayed
m_fooButton.setFocusStyle (FooButton::Focus::normalFocus);
     Focus rectangle disabled   Focus rectangle enabled

Default button indicator

To enable a default FooButton to display its standard dark border, call setFocusStyle() with FooButton::Focus::defaultFocus.

// Allow focus rectangle and default indicator to be displayed
m_fooButton.setFocusStyle (FooButton::Focus::defaultFocus);
    Default button (unpressed)   Default button (pressed)

Rendering disabled bitmaps

Use the standard MFC EnableWindow() API to enable and disable the button.  FooButton uses its original bitmap to render a disabled version.

m_fooButton.EnableWindow (TRUE);   // enable button
m_fooButton.EnableWindow (FALSE);  // disable button
     Normal   Disabled

Acknowledgement

Revision history

  • 7 Oct 2006
    • Bug Fixm_hMsimg32 should be set to NULL in destructor. (Thanks, C. Young!)
    • Bug Fix:  Memory leak in DisabledBlt(). (Thanks, Corrado Valli!)

  • 6 Mar 2005
    • Bug Fix:  Added definition of COLOR_HOTLIGHT to enable compilation on older systems.

  • 5 Mar 2005
    • Enhancement:  Added support for gradient shaded buttons.
    • Bug Fix:  Reusing a group name across dialog invocations would cause a crash in FooButton::removeFromGroup().

  • 19 Feb 2005
    • Enhancement:  Added support for colored captions.
    • Enhancement:  Removed requirement to call FooButton::reset() when your app terminates.
    • Enhancement:  Now uses standard Win2000/XP hyperlink cursor.
    • Enhancement:  Code now ASSERTs if you're not subclassing from a button control.
    • Bug Fix:  All calls to Invalidate() now validate window handle, allowing a FooButton to be safely destroyed when clicked.

  • Fixed typo in default state rendering logic
  • 17 Jul 2004
    • Added support for check boxes and radio buttons
    • Fixed typo in default state rendering logic

  • 11 Jul 2004
    • Optimized fix for "unreferenced identifier" compiler warning
    • Exposed focus rectangle and default state modes
    • Added support for button groups

  • 4 Jul 2004
    Added multi-pushbutton and hyperlink styles.

  • 3 Jul 2004
    Submitted to CodeProject.

  • 12 Sep 1998
    Initial version.
  • License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    Share

    About the Author

    Ravi Bhavnani
    Technical Lead
    Canada Canada
    Ravi Bhavnani is an ardent fan of Microsoft technologies who loves building Windows apps, especially PIMs, system utilities, and things that go bump on the Internet. During his career, Ravi has developed expert systems, desktop imaging apps, marketing automation software, EDA tools, a platform to help people find, analyze and understand information, trading software for institutional investors and advanced data visualization solutions. He currently works for a company that provides enterprise workforce management solutions to large clients.

    His interests include the .NET framework, reasoning systems, financial analysis and algorithmic trading, NLP, HCI and UI design. Ravi holds a BS in Physics and Math and an MS in Computer Science and was a Microsoft MVP (C++ and C# in 2006 and 2007). He is also the co-inventor of 2 patents on software security and generating data visualization dashboards. His claim to fame is that he crafted CodeProject's "joke" forum post icon.

    Ravi's biggest fear is that one day he might actually get a life, although the chances of that happening seem extremely remote.

    You may also be interested in...

    Comments and Discussions

     
    QuestionGreat work,but no xp style Pin
    lanmanck7-May-14 19:10
    memberlanmanck7-May-14 19:10 
    AnswerRe: Great work,but no xp style Pin
    Ravi Bhavnani8-May-14 2:25
    professionalRavi Bhavnani8-May-14 2:25 
    QuestionFast multiple clicking on a button typed "checkButton" doesn't save the m_bChecked parameter correctly Pin
    Sunny127023-Jun-12 23:25
    memberSunny127023-Jun-12 23:25 
    GeneralDouble click - not giving a second click. Pin
    Phil Outram12-Jan-10 6:16
    memberPhil Outram12-Jan-10 6:16 
    GeneralRe: Double click - not giving a second click. Pin
    Ravi Bhavnani12-Jan-10 6:18
    memberRavi Bhavnani12-Jan-10 6:18 
    GeneralRe: Double click - not giving a second click. Pin
    Phil Outram12-Jan-10 6:21
    memberPhil Outram12-Jan-10 6:21 
    QuestionUse with Common Dialogs Pin
    daxack25-Apr-09 1:35
    memberdaxack25-Apr-09 1:35 
    QuestionWhy GROUPBOX Appears to be round? Pin
    librorum19-Feb-09 15:25
    memberlibrorum19-Feb-09 15:25 
    AnswerRe: Why GROUPBOX Appears to be round? Pin
    Ravi Bhavnani19-Feb-09 15:31
    memberRavi Bhavnani19-Feb-09 15:31 
    QuestionCan't get CFont object from the button's GetFont() [modified] Pin
    guocang2-Dec-08 7:26
    memberguocang2-Dec-08 7:26 
    AnswerRe: Can't get CFont object from the button's GetFont() Pin
    Ravi Bhavnani18-Dec-08 1:30
    memberRavi Bhavnani18-Dec-08 1:30 
    GeneralGradient suggest when disable button Pin
    chogeha26-Jun-08 23:52
    memberchogeha26-Jun-08 23:52 
    GeneralRe: Gradient suggest when disable button Pin
    Ravi Bhavnani27-Jun-08 3:56
    memberRavi Bhavnani27-Jun-08 3:56 
    GeneralMissing update when changing text Pin
    K.Stein17-Oct-07 21:47
    memberK.Stein17-Oct-07 21:47 
    GeneralRe: Missing update when changing text Pin
    Ravi Bhavnani18-Oct-07 2:42
    memberRavi Bhavnani18-Oct-07 2:42 
    GeneralXP Themes Pin
    Tim Cook14-Jun-07 3:15
    memberTim Cook14-Jun-07 3:15 
    GeneralRe: XP Themes Pin
    Ravi Bhavnani14-Jun-07 7:27
    memberRavi Bhavnani14-Jun-07 7:27 
    GeneralRe: XP Themes Pin
    David Pritchard26-Mar-10 4:21
    memberDavid Pritchard26-Mar-10 4:21 
    GeneralRe: XP Themes Pin
    Jacob Skjoet9-Jun-11 22:48
    memberJacob Skjoet9-Jun-11 22:48 
    GeneralRe: XP Themes Pin
    Ravi Bhavnani10-Jun-11 1:51
    memberRavi Bhavnani10-Jun-11 1:51 
    GeneralRe: XP Themes Pin
    Jacob Skjoet10-Jun-11 2:12
    memberJacob Skjoet10-Jun-11 2:12 
    GeneralRe: XP Themes Pin
    Ravi Bhavnani10-Jun-11 2:22
    memberRavi Bhavnani10-Jun-11 2:22 
    GeneralRe: XP Themes Pin
    Ravi Bhavnani10-Jun-11 2:25
    memberRavi Bhavnani10-Jun-11 2:25 
    GeneralRe: XP Themes Pin
    David Pritchard25-Jul-11 4:53
    memberDavid Pritchard25-Jul-11 4:53 
    GeneralRe: XP Themes Pin
    Ravi Bhavnani25-Jul-11 5:05
    memberRavi Bhavnani25-Jul-11 5:05 
    GeneralRe: XP Themes Pin
    David Pritchard2-Aug-11 5:56
    memberDavid Pritchard2-Aug-11 5:56 
    GeneralRe: XP Themes Pin
    lanmanck7-May-14 19:45
    memberlanmanck7-May-14 19:45 
    GeneralRe: XP Themes [modified] Pin
    David Pritchard2-Aug-11 6:01
    memberDavid Pritchard2-Aug-11 6:01 
    GeneralRe: XP Themes Pin
    David Pritchard2-Aug-11 6:03
    memberDavid Pritchard2-Aug-11 6:03 
    GeneralRe: XP Themes Pin
    Member 26088026-Aug-11 14:08
    memberMember 26088026-Aug-11 14:08 
    GeneralRe: XP Themes Pin
    Ravi Bhavnani27-Aug-11 3:39
    memberRavi Bhavnani27-Aug-11 3:39 
    GeneralRe: XP Themes Pin
    David Pritchard2-Aug-11 22:54
    memberDavid Pritchard2-Aug-11 22:54 
    GeneralRe: XP Themes Pin
    David Pritchard2-Aug-11 23:58
    memberDavid Pritchard2-Aug-11 23:58 
    GeneralRe: XP Themes Pin
    David Pritchard3-Aug-11 0:04
    memberDavid Pritchard3-Aug-11 0:04 
    GeneralRe: XP Themes Pin
    David Pritchard3-Aug-11 0:05
    memberDavid Pritchard3-Aug-11 0:05 
    GeneralRe: XP Themes Pin
    Ravi Bhavnani3-Aug-11 1:18
    memberRavi Bhavnani3-Aug-11 1:18 
    GeneralRe: XP Themes Pin
    David Pritchard3-Aug-11 9:49
    memberDavid Pritchard3-Aug-11 9:49 
    GeneralBug fix for FooButton::reset() Pin
    JavaBear23-Apr-07 8:07
    memberJavaBear23-Apr-07 8:07 
    Generalneed to initialize code at reset() function... Pin
    Hualsoo,KIM5-Jan-07 2:33
    memberHualsoo,KIM5-Jan-07 2:33 
    GeneralRe: need to initialize code at reset() function... Pin
    Ravi Bhavnani11-Jan-07 2:12
    memberRavi Bhavnani11-Jan-07 2:12 
    QuestionIs this possible? Pin
    Neounk21-Dec-06 7:58
    memberNeounk21-Dec-06 7:58 
    AnswerRe: Is this possible? Pin
    Ravi Bhavnani21-Dec-06 8:12
    memberRavi Bhavnani21-Dec-06 8:12 
    GeneralRe: Is this possible? Pin
    Neounk21-Dec-06 10:37
    memberNeounk21-Dec-06 10:37 
    GeneralAntibounce on check-button type Pin
    roby6812-Dec-06 20:34
    memberroby6812-Dec-06 20:34 
    GeneralBug in OnLButtonUp() [modified] Pin
    Alex Cohn7-Dec-06 3:23
    memberAlex Cohn7-Dec-06 3:23 
    AnswerRe: Bug in OnLButtonUp() Pin
    Ravi Bhavnani7-Dec-06 3:47
    memberRavi Bhavnani7-Dec-06 3:47 
    GeneralAbout warning C4482... Pin
    ILoveMJ30-Nov-06 21:06
    memberILoveMJ30-Nov-06 21:06 
    AnswerRe: About warning C4482... Pin
    Ravi Bhavnani1-Dec-06 8:12
    memberRavi Bhavnani1-Dec-06 8:12 
    AnswerRe: About warning C4482... Pin
    phord9-Aug-07 8:22
    memberphord9-Aug-07 8:22 
    GeneralButton Color Pin
    jamesroy30-Nov-06 15:58
    memberjamesroy30-Nov-06 15:58 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Terms of Use | Mobile
    Web04 | 2.8.150901.1 | Last Updated 7 Oct 2006
    Article Copyright 2004 by Ravi Bhavnani
    Everything else Copyright © CodeProject, 1999-2015
    Layout: fixed | fluid