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

XGroupBox - an MFC groupbox control to display text and icon

0.00/5 (No votes)
2 Sep 2008 5  
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.

Introduction

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.

Features

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:

screenshot

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:

screenshot

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:

screenshot

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
    //{{AFX_DATA(CXGroupBoxTestDlg)
    enum { IDD = IDD_XGROUPBOXTEST_DIALOG };
    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;
    //}}AFX_DATA

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)
                .SetAlignment(CXGroupBox::right);

    m_XGroupBox3.SetAlignment(CXGroupBox::center);

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

    if (m_hGlobeIcon)
        ::DestroyIcon(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(), 
                                    MAKEINTRESOURCE(nIconId[m_nColor]),
                                    IMAGE_ICON, nSize, nSize, LR_DEFAULTCOLOR);
        ASSERT(m_hGlobeIcon);
    }

    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);
    }
    else
    {
        // 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);
        pControls[i]->SetWindowText(str);
    }

    if (m_nStyle == 0 || m_nStyle == 1)
        m_XGroupBox3.SetWindowText(MAKEINTRESOURCE(IDS_GROUPBOX3_TEXT), FALSE);

    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);

    RedrawWindow();

    for (i = 0; i < 4; i++)
        pControls[i]->RedrawWindow();
}

References

More Groupbox Control Articles

Revision History

Version 1.0 - 2008 September 2

  • Initial public release

Usage

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.

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