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

XGroupBox - an MFC groupbox control to display text and icon

, 2 Sep 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
XGroupBox is an MFC control that displays a flicker-free groupbox with text and/or icon. You can use this to display either a standard groupbox or a header-only groupbox.


Groupboxes are one of my favorite UI elements. They collect together related controls, and guide the user through non-trivial user interfaces. It seems natural to display an icon in the groupbox header, since studies have shown that graphic images are more quickly recognized by users.

This control implements two styles of groupboxes: a standard groupbox that allows you to display text and/or an icon; and a header-only groupbox, which offers same features, but only displays a single line, rather than a frame. The header-only style offers advantages when used in a very compressed UI, since it requires less screen real estate.


Here are features which XGroupBox implements:
screenshot Replacement for Win32 groupbox, without the flicker when resized
screenshot Display icon and/or text
screenshot Display standard groupbox or header-only groupbox
screenshot Easy to set colors, font, and horizontal alignment
screenshot Support theming or custom colors (for header-only style, theming is not supported)
screenshot Allow for disabling of control and optionally disabling all child controls contained within groupbox
screenshot When control is disabled, icon will be displayed in grayscale

XGroupBox Demo

The demo app shows some examples of what this control can do:


This dialog is resizable and shows difference in flickering between XGroupBox and Win32 groupbox.

Header-Only Style

A separate dialog shows how header-only style may be used:


XGroupBox Example Gallery

There is another dialog that runs through different option settings and shows you the code used to generate the XGroupBox that is being displayed:


XGroupBox API

Function Description
CXGroupBox& EnableTheme(BOOL bEnable, BOOL bRedraw = TRUE) Enables/disables use of themes (if available)
BOOL EnableWindow(BOOL bEnable = TRUE, BOOL bRecurseChildren = FALSE) Enables/disables control, and optionally its children
ALIGNMENT GetAlignment() Retrieves control alignment; this is alignment of text and icon
BOOL GetBold() Retrieves bold setting
COLORREF GetBorderColor() Retrieves border color
BORDER_STYLE GetBorderStyle() Retrieves border style (flat or etched)
BOOL GetDisabledStyle() Returns TRUE if control will display disabled state
CFont* GetFont() Retrieves pointer to CFont member variable
BOOL GetFont(LOGFONT *pLF) Retrieves LOGFONT struct for font
CString GetFontFaceName() Retrieves font face name
int GetFontPointSize() Retrieves font point size
ALIGNMENT GetIconAlignment() Retrieves icon alignment (left or right of text)
int GetIconSpacing() Retrieves spacing between icon and text
void GetMargins(int& nXMargin, int& nYMargin) Retrieves x and y margins
CONTROL_STYLE GetControlStyle() Retrieves control style (groupbox or header)
COLORREF GetTextColor() Retrieves text color
CXGroupBox& SetAlignment(ALIGNMENT eAlign, BOOL bRedraw = TRUE) Sets control alignment (for text and icon)
CXGroupBox& SetBold(BOOL bBold, BOOL bRedraw = TRUE) Sets bold font
CXGroupBox& SetBorderColor(COLORREF crBorder, BOOL bRedraw = TRUE) Sets border color
CXGroupBox& SetBorderStyle(BORDER_STYLE eStyle, BOOL bRedraw = TRUE) Sets border style (flat or etched)
CXGroupBox& SetControlStyle(CONTROL_STYLE eStyle, BOOL bRedraw = TRUE) Sets control style (groupbox or header)
CXGroupBox& SetDisabledStyle(BOOL bShowDisabledState, BOOL bRedraw = TRUE) Sets whether control will display disabled state
CXGroupBox& SetFont(CFont *pFont, BOOL bRedraw = TRUE) Sets font via CFont object
CXGroupBox& SetFont(LOGFONT * pLogFont, BOOL bRedraw = TRUE) Sets font via LOGFONT struct
CXGroupBox& SetFont(LPCTSTR lpszFaceName, int nPointSize, BOOL bRedraw = TRUE) Sets font face name and point size
CXGroupBox& SetIcon(HICON hIcon, UINT nIconSize = 16, BOOL bRedraw = TRUE) Sets icon via HICON
CXGroupBox& SetIcon(UINT nIconId, UINT nIconSize = 16, BOOL bRedraw = TRUE) Sets icon via resource id
CXGroupBox& SetIconAlignment(ALIGNMENT eAlign, BOOL bRedraw = TRUE) Sets icon alignment (left or right of text)
CXGroupBox& SetIconSpacing(int nIconSpacing, BOOL bRedraw = TRUE) Sets spacing between icon and text
CXGroupBox& SetImageList(CImageList * pImageList, int nIconNo, BOOL bRedraw = TRUE) Sets image list for icons
CXGroupBox& SetMargins(int nXMargin, int nYMargin, BOOL bRedraw = TRUE) Sets x and y margins
CXGroupBox& SetTextColor(COLORREF cr, BOOL bRedraw = TRUE) Sets text color
CXGroupBox& SetWindowText(LPCTSTR lpszText, BOOL bRedraw = TRUE) Sets text

How to Use

Step 1 - Add Files

To integrate XGroupBox into your app, you first need to add following files to your project:

  • XGroupBox.cpp
  • XGroupBox.h
  • XVisualStyles.h

Step 2 - Add Header File to Your Source Module

In the module where you want to use XGroupBox (typically this will be dialog header file), include header file XGroupBox.h.

Step 3 - Add Button Control to Dialog

Using the VS IDE resource editor, add a static control where you want the XGroupBox control. Here is a portion of the .rc file for demo app:
  LTEXT        "XGroupBox 1",IDC_GROUPBOX1,10,146,110,32
  LTEXT        "Danger Will Robinson!",IDC_STATIC,43,165,73,8
  LTEXT        "XGroupBox 2",IDC_GROUPBOX2,130,146,100,32
  LTEXT        "~ My Music ~",IDC_STATIC,164,165,45,8
  LTEXT        "XGroupBox 3",IDC_GROUPBOX3,10,183,220,42,0
  LTEXT        "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean nec neque eu.",
               IDC_STATIC,18,202,132,17,NOT WS_GROUP
  PUSHBUTTON   "Button",IDC_BUTTON2,165,201,50,14
  LTEXT        "XGroupBox 4",IDC_GROUPBOX4,10,230,220,42
  LTEXT        "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean nec neque eu.",
               IDC_STATIC,18,249,132,17,NOT WS_GROUP
  PUSHBUTTON   "Button",IDC_BUTTON3,165,248,50,14
Note that all the static controls use the LTEXT tag - the alignment of text and icon is done with the SetAlignment() function.

Next, associate static control with CStatic class variable. Then replace CStatic with CXGroupBox:

// Dialog Data
    CXGroupBox    m_XGroupBox1;
    CXGroupBox    m_XGroupBox2;
    CXGroupBox    m_XGroupBox3;
    CXGroupBox    m_XGroupBox4; 
    int           m_nStyle;
    int           m_nAlign;
    int           m_nColor;
    BOOL          m_bEnableThemes;
    BOOL          m_bDisable;
    int           m_nBorderStyle;

Step 4 - Add Initialization Code

Add initialization code to your OnInitDialog() function. In demo app, one-time initialization is performed in OnInitDialog():
    // one-time initialization

    m_XGroupBox1.SetTextColor(RGB(255,0,0), FALSE)
                .SetBold(TRUE, FALSE);

    m_XGroupBox2.SetTextColor(RGB(34,139,34), FALSE)        // forestgreen
                .SetBold(TRUE, FALSE)
                .SetFont(_T("Comic Sans MS"), 10, FALSE)


    m_XGroupBox4.SetFont(_T("Comic Sans MS"), 14, FALSE);
Dynamic initialization is performed in OnChange():
void CXGroupBoxTestDlg::OnChange()

    if (m_hGlobeIcon)
    m_hGlobeIcon = 0;

    static UINT nIconId[] = { IDI_T256, IDI_T32BPP };

    static CXGroupBox *pControls[4] = { &m_XGroupBox1, &m_XGroupBox2, 
                                        &m_XGroupBox3, &m_XGroupBox4 };

    int i = 0;

    int nSize = m_nColor ? 32 : 16;

    if (m_nStyle == 0 || m_nStyle == 2)
        // Note: you can also use LoadIcon(), if you are sure that 
        // you will get correct icon
        m_hGlobeIcon = (HICON) ::LoadImage(AfxGetInstanceHandle(), 
                                    IMAGE_ICON, nSize, nSize, LR_DEFAULTCOLOR);

    if (m_hGlobeIcon)
        CImageList list;
        VERIFY(list.Create(nSize, nSize, ILC_COLOR32|ILC_MASK, 2, 1));
        VERIFY(list.Add(m_hGlobeIcon) == 0);

        m_XGroupBox1.SetIcon(IDI_REDX, 32, FALSE);
        m_XGroupBox2.SetIcon(IDI_AUDIOCD, 32, FALSE);
        m_XGroupBox3.SetImageList(&list, 0, FALSE);
        m_XGroupBox4.SetImageList(&list, 0, FALSE);
        // no icon
        for (i = 0; i < 4; i++)
            pControls[i]->SetIcon((HICON)0, nSize, FALSE);

    for (i = 0; i < 4; i++)
        CString str = _T(&quot;&quot;);
        if (m_nStyle == 0 || m_nStyle == 1)
            str.Format(_T(&quot;XGroupBox %d&quot;), i+1);

    if (m_nStyle == 0 || m_nStyle == 1)

    CXGroupBox::ALIGNMENT eAlign = CXGroupBox::left;
    if (m_nAlign)
        eAlign = CXGroupBox::right;
    for (i = 0; i < 4; i++)
        pControls[i]->SetIconAlignment(eAlign, FALSE);

    for (i = 0; i < 4; i++)
        pControls[i]->SetBorderStyle((CXGroupBox::BORDER_STYLE) m_nBorderStyle, FALSE);


    for (i = 0; i < 4; i++)


More Groupbox Control Articles

Revision History

Version 1.0 - 2008 September 2

  • Initial public release


This software is released into the public domain. You are free to use it in any way you like, except that you may not sell this source code. If you modify it or extend it, please to consider posting new code here for everyone to share. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.


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


About the Author

Hans Dietrich
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.
Recently, I have moved to Los Angeles where I am doing consulting and development work.
For consulting and custom software development, please see

Comments and Discussions

GeneralRe: Easy 5... as usual PinmvpHans Dietrich2-Sep-08 8:17 
GeneralRe: Easy 5... as usual Pinmemberugly beast2-Sep-08 10:04 
GeneralRe: Easy 5... as usual PinmemberFranc Morales2-Sep-08 10:06 
General1-vote PinmemberIvan Krasko8-Sep-08 8:29 
This may be a little off topic, but I sincerely believe that '1 vote' is probably a mistake similar to what I did long time ago(nobody can seriously vote 1 for this good article):
When I started to use CodeProject it happened that I confused the voting numbers (1 to 5) for the page numbers and by trying to go back to the first page I actually voted 1. Well, then I realized what I did, felt bad and since then pay more attention to what I really click on.
Just wondering how many users may make the same mistake. Maybe I should suggest to Chris Mauder to change the voting format... Smile | :)
GeneralRe: 1-vote (correction) PinmemberIvan Krasko8-Sep-08 8:37 
GeneralYou do cool stuff! PinmemberIlíon2-Sep-08 7:19 
GeneralExcellent! PinmemberNGS 5496722-Sep-08 6:08 
GeneralCool PinmemberZhang Zhixiang2-Sep-08 6:05 

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.150327.1 | Last Updated 2 Sep 2008
Article Copyright 2008 by Hans Dietrich
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid