Click here to Skip to main content
Click here to Skip to main content

CCheckSK - An Extended Check-box class

By , 19 Aug 2003
 

Sample Image

Introduction

This class is derived from the MFC CButton. It supports the following features:

  1. Showing of On/Off LEDs to indicate state of the check box
  2. Showing an icon to indicate state of the check box. Icon can be specified using a resource ID, filename or HICON.
  3. Left/Center/Right aligned texts
  4. Text on the left or right of the LED
  5. Enabled/disabled check boxes
  6. Tool tips

This article demonstrates how to extend MFC to subclass common controls and to apply owner drawing to give them any desired look.

Using the code

To use the class follow the steps:

  1. Add the files CCheckSK.h and CCheckSK.cpp to your project.
  2. Create check boxes on the dialog.
  3. Open the class wizard and create control variables for the check boxes. Choose "Control" for the "Category" and "CButton" for the "Variable Type".
  4. Include CCheckSK.h in the .h file for your dialog class (in the demo the file is checkDlg.h)
  5. If you had named the check-box variable m_chk then in the header file for the dialog, there will be a line CButton m_chk; Replace the CButton with CCheckSK
  6. At the end of OnInitDialog of your dialog class, add calls to the appropriate methods in CCheckSK
    BOOL CCheckDlg::OnInitDialog()
    {
        ... 
        m_chk1.SetCheck(TRUE);
        m_chk1.SetLedColor(RGB(255, 0, 0), RGB(128, 0, 0));
        m_chk1.SetToolTip("Click on this to change the state");
    
        m_chk5.SetIcon(IDI_ON, IDI_OFF);
        ...
    }
  7. If you want to change the look of the check boxes later, you can call any of these methods from your code at run time.

How the code works

We start by deriving the CCheckSk class from the CButton MFC.

class CCheckSK : public CButton
{
    ....
}

To make the control owner drawn, the BS_OWNERDRAW style needs to be added to the window style. For this subclassing is used. To do this the PreSubclassWindow method is overridden as follows.

void CCheckSK::PreSubclassWindow() 
{
    UINT nBS = GetButtonStyle();
    
    //  the button should not be owner draw
    ASSERT((nBS & SS_TYPEMASK) != BS_OWNERDRAW);

    //  This class supports only check boxes
    ASSERT(nBS & BS_CHECKBOX);
    
    // Switch to owner-draw
    ModifyStyle(SS_TYPEMASK, BS_OWNERDRAW, SWP_FRAMECHANGED);
    
    m_nStyle = GetWindowLong(GetSafeHwnd(), GWL_STYLE);

    CButton::PreSubclassWindow();
}

Once the owner-draw style has been set, the framework will call the DrawItem method each time it requires the control to be redrawn. So this method has to be implemented and all code to draw the LED or display the icon has to be added to it. The implementation of this method is a bit long and the following snippet just gives the flow

void CCheckSK::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
    //  this class works only for push buttons
    ASSERT (lpDIS->CtlType == ODT_BUTTON);
    
    //  get the device context pointer to draw into
    CDC* pDC = CDC::FromHandle(lpDIS->hDC);

    //  get button state, selected? has focus? disabled?
   
    //  draw bounding rectangle with color based on whether
    //  the mouse is over the check box

    //  if check box has focus then draw the focus rectangle
    
    //  calculate LED's and text's rectangle
    
    //  If icon is given then draw the icon 
    //  otherwise draw the LED using GDI functions
 
    //  Calculate the rectangle for the text based on the
    //  horizontal alignment style of the check box
    
    //  if the button is disabled then draw etched text or draw plain text

    //  Release all resources
 
}

Methods

The following methods are present in CDialogSK class:

  1. DWORD SetIcon(int nIconOn, int nIconOff);

    Sets the icon based on resource ID

  2. DWORD SetIcon(HICON hIconOn, HICON hIconOff);

    Sets the icon based on handle to a icon

  3. DWORD SetIcon(LPCTSTR lpszFileNameIn, LPCTSTR lpszFileNameOut);

    Sets the icon based on the name of an icon file

  4. BOOL SetLedColor(COLORREF colLedOn, COLORREF colLedOff);

    If any icons are not used then this method is used to set the color of the on/off LED

  5. BOOL SetLedSize (int nSize);

    The size of the LED is changed with this method.

  6. void SetToolTip (LPCTSTR lpszText);

    The tool tip for the check box can be changed using this method

History

  • This is the initial version.

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

About the Author

abhinaba
Web Developer
United States United States
Member
I just love coding. I started programming in 1995 with BASIC and then moved through Cobol, Pascal, Prolog, C, C++, VB, VC++ and now C#/.NET.
 
I received a Bachelor of Technology degree in Computer Science from University of Calcutta in 2001.
 
I worked for some time in Texas Instruments, Adobe Systems and now in Microsoft India Development Center in the Visual Studio Team Systems.
 
I am from the City of Joy, Kolkata in India, but now live and code Hyderabad.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 1memberMember 1869129 Jun '09 - 23:18 
lame work
GeneralICON usagememberpaulooch195822 Dec '05 - 14:33 
First of all I love this class! Simple yet exactly what I was looking for.
 

One question though:
 
What color do you use as the mask for the bitmap? The part around the edge that is tranparent? It seems to be an olive green, but I have bitmaps where the mask is black (or white) . How can I change the mask color so I can use my bitmaps without recoloring them?
 

Thanks,
Paul
GeneralRe: ICON usagememberabhinaba23 Dec '05 - 6:26 
This class right now supports ICONS and not bitmaps. ICONS support transparent color which is shown in the VC IDE as Teal (some what like Olive-green).
 
In case you need to use the class AS IS you'll need to convert your bitmaps to ICONS or else you need to extend the class for bitmaps as well.
 
Hope this helps....
 
==========================
AB => Code and let code
Go to my home
==========================
GeneralSmall BugmemberCodeHead6 Sep '05 - 4:15 
First off, let me say this is nicely done!
The problem I found is that the handler for ON_BN_CLICKED in the dialog class is never called when you click on a checkbox.   You need to add a PostMessage call in the OnClicked handler:
void CCheckSK::OnClicked()
{
   m_bCheck = !m_bCheck;
   Invalidate();
   GetParent()->PostMessage(WM_COMMAND, GetDlgCtrlID(),BN_CLICKED);
}
 
Regards,
Eric
 
-- modified at 10:31 Tuesday 6th September, 2005
GeneralRe: Small Bugmemberedwardking6 Mar '08 - 3:59 
Thanks for that.
Questionhow to use of functional keysmemberiipc9 Jul '04 - 19:33 
how can we use functional keys for controlling the 'Play','Pause','Skip','Stop' etc. keys from keyboard.Sigh | :sigh:
 
ankoor
GeneralCapturing/Saving the selected dialogmemberaparajita11 Jun '04 - 14:47 
How to capture and save the selected dialog as a ".bmp" file?
 
Aparna
GeneralRe: Capturing/Saving the selected dialogmemberabhinaba13 Jun '04 - 22:25 
  1. Select the dialog
  2. Hold Alt button down and hit the print screen button (Alt+Print Screen) to capture the dialog.
  3. Then paste into your favourite image editor or MS Paint
  4. save into any supported format
Hope this helps
 
==========================
AB => Code and let code
Go to my home
==========================
Generalbugs in the codememberabhinaba14 Jan '04 - 17:53 
A bug resulting out of a typo has been found in the class thanks to Kerry Graham. The bug leads to freeing of the m_hIconOn resource twice instead of releasing m_hIconOff. The fix is as follows.
 
Change the CCheckSK::FreeResources method to the following.
 
void CCheckSK::FreeResources()
{
   if (m_hIconOn.hIcon)  ::DeleteObject(m_hIconOn.hIcon);
   if (m_hIconOff.hIcon) ::DeleteObject(m_hIconOff.hIcon);
 
   m_hIconOn.hIcon  = NULL;
   m_hIconOff.hIcon = NULL;
}

 
==========================
AB => Code and let code
Go to my home
==========================
GeneralGreat Workmemberministerofwar13 Oct '03 - 10:06 
Just what I need! Smile | :)
 
You might want to consider expanding the flexibility of the class by adding methods to cancel thr mouse hover coloring, the focus rectangle etc.
 
There is one problem that I've found. Try coloring the on/off colors with SetLedColor(RGB(0, 255, 0), RGB(255, 0, 0)) and you see that one of the on position color has thin edges of the off color.
 
Again, I must say - GREAT WORK!

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 20 Aug 2003
Article Copyright 2003 by abhinaba
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid