Click here to Skip to main content
11,704,107 members (48,602 online)
Click here to Skip to main content

XEmphasisButton - bold and underlined text in a non-ownerdraw button

, 23 May 2007 CPOL 119.3K 855 111
Rate this:
Please Sign up or sign in to vote.
XEmphasisButton allows you to display buttons with bold and underlined text without requiring ownerdraw. This means that the button is perfectly compatible with XP themes, and also works on previous Windows versions.

Introduction

Recently my new client wanted a custom button for the new consumer application that I am building for him. Oh oh, I thought; buttons are difficult, because of the many states and modes you have to handle. Even worse, ownerdraw buttons require special treatment to look right under themed XP. The button my client wanted was similar to what is displayed when you select Search... from Explorer right-click menu:

screenshot The text of checkboxes is displayed in bold when they are selected.

Mousing over one of these buttons produces another effect:

screenshot When the mouse cursor is moved over a checkbox, its text is underlined.

The same two effects occur with radio buttons that are displayed on the Search panel.

Now my only question was, "How did Microsoft implement these?" Is it possible these buttons are not really ownerdraw? To investigate further, I turned to one of my favorite programming tools, HPS HwndSpy. To my relief, HPS HwndSpy showed that buttons were not ownerdraw:

screenshot

Implementation Details

Now that I was sure I could implement this button without needing to make them ownerdraw, I decided that API could be very simple; the only option was display state: bold, underlined, or bold and underlined. So XEmphasisButton has two public APIs:

Emphasis GetEmphasis()   { return m_eEmphasis; }

void SetEmphasis(Emphasis eEmphasis)
{
    m_eEmphasis = eEmphasis;
    SetEmphasisFont();
}

The choices for parameter are given by enum:

enum Emphasis
{
    NONE = 0,
    BOLD,         // button text will be bold if GetCheck() is TRUE
    UNDERLINE,    // button text will be underlined if mouse over
    BOLD_AND_UNDERLINE
};

Since emphasis state is limited to four cases, programming is fairly simple. In PreSubclassWindow(), I create four fonts, and in DefWindowProc() I handle three messages:

  • BM_SETCHECK — this message is sent when the check state of radio button or check box has changed:
    if (message == BM_SETCHECK)
    {
        if (wParam == BST_CHECKED)
        {
            if (m_eEmphasis == BOLD || m_eEmphasis == BOLD_AND_UNDERLINE)
            {
                // button should be bolded
                if (!m_bBold)
                {
                    if (m_bUnderline)
                        SetFont(&m_fontBoldAndUnderline);
                    else
                        SetFont(&m_fontBold);
                    m_bBold = TRUE;
                }
            }
        }
    
        if (wParam == BST_UNCHECKED)
        {
            if (m_eEmphasis == BOLD || m_eEmphasis == BOLD_AND_UNDERLINE)
            {
                // button should not be bolded
                if (m_bBold)
                {
                    if (m_bUnderline)
                        SetFont(&m_fontUnderline);
                    else
                        SetFont(&m_fontNormal);
                    m_bBold = FALSE;
                }
            }
        }
    }
    
  • WM_MOUSEMOVE — this message is sent when cursor moves over button. I use it to detect when cursor has just entered button's client area, to enable underlining:
    else if (message == WM_MOUSEMOVE)
    {
        if (!m_bOverControl)        // cursor has just moved over control
        {
            m_bOverControl = TRUE;
    
            if (m_eEmphasis == UNDERLINE ||
                m_eEmphasis == BOLD_AND_UNDERLINE)
            {
                // button should be underlined
                if (!m_bUnderline)
                {
                    if (m_bBold)
                        SetFont(&m_fontBoldAndUnderline);
                    else
                        SetFont(&m_fontUnderline);
    
                    m_bUnderline = TRUE;
                }
    
                SetTimer(1, 100, NULL);    // use timer to detect when
                                           // mouse leaves
            }
        }
    }
    
  • WM_TIMER — timer is used to detect when mouse leaves client area of button:
    else if (message == WM_TIMER)
    {
        if (m_bOverControl)    // only do this if previously over button
        {
            CRect rect;
            GetWindowRect(&rect);
    
            CPoint point;
            GetCursorPos(&point);    // always screen coordinates
    
            if (!rect.PtInRect(point))
            {
                // not over button, so remove underlining
                if (m_bUnderline)
                {
                    if (m_bBold)
                        SetFont(&m_fontBold);
                    else
                        SetFont(&m_fontNormal);
    
                    m_bUnderline = FALSE;
                }
                m_bOverControl = FALSE;
                KillTimer(wParam);
            }
        }
    }
    

Demo App

The demo app allows you to try out various combinations of display attributes:

screenshot

How To Use

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

  • XEmphasisButton.cpp
  • XEmphasisButton.h

Next, include header file XEmphasisButton.h in appropriate project files (usually, this will be in header file for dialog class). Then replace declaration of button control with this:

CXEmphasisButton   m_MyButton;
(use whatever variable name already exists).

Now you are ready to start using CXEmphasisButton. In dialog's OnInitDialog() function, insert line

m_MyButton.SetEmphasis(CXEmphasisButton::BOLD_AND_UNDERLINE);
(use whatever display attributes you wish).

Revision History

Version 1.0 — 2006 August 15

  • 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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

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 www.hdsoft.org.






You may also be interested in...

Comments and Discussions

 
GeneralHere were are in 2012 Pin
Mike Gaskey25-Mar-12 8:35
memberMike Gaskey25-Mar-12 8:35 
GeneralMy 5 and thanks Pin
Franc Morales26-Jun-08 21:20
memberFranc Morales26-Jun-08 21:20 
GeneralRe: My 5 and thanks Pin
Hans Dietrich26-Jun-08 21:39
mvpHans Dietrich26-Jun-08 21:39 
GeneralRe: My 5 and thanks Pin
Franc Morales27-Jun-08 0:08
memberFranc Morales27-Jun-08 0:08 
GeneralNice article Pin
Tamal Saha23-Oct-07 10:21
memberTamal Saha23-Oct-07 10:21 
AnswerRe: Nice article Pin
Hans Dietrich15-Apr-11 3:26
mentorHans Dietrich15-Apr-11 3:26 
QuestionWM_MOUSELEAVE? Pin
Perry Zhu4-Jun-07 21:22
memberPerry Zhu4-Jun-07 21:22 
AnswerRe: WM_MOUSELEAVE? Pin
Hans Dietrich4-Jun-07 23:09
mvpHans Dietrich4-Jun-07 23:09 
GeneralRe: WM_MOUSELEAVE? Pin
Perry Zhu5-Jun-07 22:35
memberPerry Zhu5-Jun-07 22:35 
GeneralCompliment Pin
virtualnik30-May-07 8:59
membervirtualnik30-May-07 8:59 
GeneralI've been meaning to thank you... Pin
Tom Guidarelli29-May-07 5:56
memberTom Guidarelli29-May-07 5:56 
GeneralRe: I've been meaning to thank you... Pin
Hans Dietrich29-May-07 16:40
mvpHans Dietrich29-May-07 16:40 
GeneralNice control! Pin
J Whattam23-Aug-06 16:03
memberJ Whattam23-Aug-06 16:03 
GeneralSimple, but very useful Pin
Anna-Jayne Metcalfe21-Aug-06 19:41
memberAnna-Jayne Metcalfe21-Aug-06 19:41 
GeneralVery nice!...and a question about menu items in bold Pin
Alexandru Matei20-Aug-06 23:34
memberAlexandru Matei20-Aug-06 23:34 
GeneralRe: Very nice!...and a question about menu items in bold Pin
Hans Dietrich21-Aug-06 16:49
memberHans Dietrich21-Aug-06 16:49 
GeneralRe: Very nice!...and a question about menu items in bold Pin
Anna-Jayne Metcalfe21-Aug-06 19:39
memberAnna-Jayne Metcalfe21-Aug-06 19:39 
GeneralExcellent as always Pin
John R. Shaw20-Aug-06 6:25
memberJohn R. Shaw20-Aug-06 6:25 
GeneralRe: Excellent as always Pin
Hans Dietrich20-Aug-06 6:37
memberHans Dietrich20-Aug-06 6:37 
AnswerRe: Excellent as always Pin
KarstenK24-Aug-06 3:17
memberKarstenK24-Aug-06 3:17 
GeneralRe: Excellent as always Pin
Hans Dietrich20-Aug-06 19:29
memberHans Dietrich20-Aug-06 19:29 
GeneralRe: Excellent as always Pin
John R. Shaw22-Aug-06 6:41
memberJohn R. Shaw22-Aug-06 6:41 
GeneralExcellent! Pin
Wes Aday18-Aug-06 6:07
memberWes Aday18-Aug-06 6:07 
GeneralGreat job !!! Pin
Leopoldo Peralta17-Aug-06 13:36
memberLeopoldo Peralta17-Aug-06 13:36 
GeneralOther features Pin
alexey N16-Aug-06 20:26
memberalexey N16-Aug-06 20:26 

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
Web03 | 2.8.150819.1 | Last Updated 23 May 2007
Article Copyright 2006 by Hans Dietrich
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid