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

CCaptionButton (buttons for the titlebar)

, 13 Jun 2004
Rate this:
Please Sign up or sign in to vote.
Bitmap - buttons for the Titlebar

Sample Image - CCaptionButton.gif

Here are some more images with different button states:

DeActive Image - DeActive.gif

Mouse hover state:

Highlight Image - Highlight.gif

Introduction

This class inserts a variable number of bitmaps to the caption of your dialog and handles them like buttons (next to the close, maximize or minimize button). This means the size and the position will be calculated no matter if there is only 1 button (to close the Dialog) or 3 buttons (to close/maximize/minimize). It is also possible to draw the button to a dialog that has the toolwindow flag or the resizable flag set. The button shows a highlighted state if the mouse hovers above it and gets disabled if the window is deactivated. The reason for me to build this class was to bring a button to the caption of a dialog without using DrawFrameControl, just to get some experience with Bitmaps and the NonClient area.

BTW: Constructive criticism is always welcome! Smile | :)

Using the code:

The code in the demo project is well documented (at least in my view of things Wink | ;-) ). Take a look!

  1. Add the files CaptionButton.h and CaptionButton.cpp to your project and include the header.
    #include "CaptionButton.h"
  2. Create a member variable of class CCaptionButton.
    i.e.   CCaptionButton *m_pCapBtn // a pointer to CCaptionButton
  3. Call the static function CCaptionButton::InitCapBtn in your dialog's OnInitDialog() handler.
    CCaptionButton::InitCapBtn(m_hWnd);
    • HWND m_hWnd is the handle of the window where the button should be placed.
  4. While we are in the OnInitDialog() part of your dialog's source file, we tell the class some details.

    Therefore we use the member function SetBmpID:

    m_pCapBtn->SetBmpID(1, IDB_LAMPOFF, IDB_LAMPON, FALSE);
    • UINT n (in this case 1) is the number of the button (e.g.: 1 is the rightmost button, then comes button number 2 on the left side of button number 1...)
    • UINT IDB_LAMPOFF is the bitmap for the unpressed button
    • UINT IDB_LAMPON is the bitmap for the button in the pressed state of the button. This can be left clear in case you prefer to use the same bitmap for both button states (pressed/unpressed)
    • BOOL FALSE presents the kind of the button (checkbutton or not). Important only for the hover-drawing.

    You are able to use this function to change the bitmaps somewhere in the code as long as the first argument remains the same.

  5. Now, we have to react on the message WMU_HITCAPBUTTON:

    We want to take some action when the button in the caption is clicked. Every time our button is clicked, a message is sent to our window. That's why we have to add a handler for the registered-message WMU_HITCAPBUTTON. Follow these simple steps to accomplish the task:

    • You define the handler OnWMU_Hitcapbutton in the message handler part of your dialog class' header file. Add the declaration:
      • afx_msg LRESULT OnWMU_Hitcapbutton(WPARAM wParam, LPARAM lParam);
    BEGIN_MESSAGE_MAP(CTitleBarButtonDlg, CDialog)
            //{{AFX_MSG(CTitleBarButtonDlg)
            virtual BOOL OnInitDialog();
            afx_msg void OnPaint();
            afx_msg HCURSOR OnQueryDragIcon();
            afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);
            afx_msg void OnNcPaint();
            afx_msg void OnDestroy();
            afx_msg BOOL OnNcActivate(BOOL bActive);
            afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point);
            //}}AFX_MSG
            afx_msg LRESULT OnWMU_Hitcapbutton(WPARAM wParam, LPARAM lParam);
    DECLARE_MESSAGE_MAP()
    • Create an entry in the table to dispatch on these messages, therefore you declare the registered message and add an entry in the message map of your dialog class' source file:
      • For the Registered Message: DECLARE_USER_MESSAGE(WMU_HITCAPBUTTON)
      • The message map entry: ON_REGISTERED_MESSAGE(WMU_HITCAPBUTTON, OnWMU_Hitcapbutton)
    // announce the registered message:
    
    DECLARE_USER_MESSAGE(WMU_HITCAPBUTTON)
    
    BEGIN_MESSAGE_MAP(CTitleBarButtonDlg, CDialog)
            //{{AFX_MSG_MAP(CTitleBarButtonDlg)
            ON_WM_PAINT()
            ON_WM_QUERYDRAGICON()
            ON_WM_NCLBUTTONDOWN()
            ON_WM_NCPAINT()
            ON_WM_DESTROY()
            ON_WM_NCACTIVATE()
            ON_WM_NCMOUSEMOVE()
            //}}AFX_MSG_MAP
            ON_REGISTERED_MESSAGE(WMU_HITCAPBUTTON, OnWMU_Hitcapbutton)
    END_MESSAGE_MAP()

    Please notice that the entries in the message map are written outside the //}}AFX_MSG - MFC-Tags!

    • Now, when your class receives the WMU_HITCAPBUTTON message, it will call the handler for this message which should look like this:
    /***********************************************************************
    *   Message Name:            WMU_HITCAPBUTTON
    *   Inputs:
    *     WPARAM: (UINT)wParam = Nomba of Button
    *     LPARAM: (BOOL)lParam = Button state (Pressed=TRUE/Released=FALSE)
    *
    *   Result: LRESULT
    *                       Logically void, 0, always
    *
    *   Effect: represents the # of the Button (if there is more than one)
    *               and the button state (pressed/released)
    ***********************************************************************/
    LRESULT CTitleBarButtonDlg::OnWMU_Hitcapbutton(WPARAM wParam,
                                                      LPARAM lParam)
    {
            // Button #1 has been hit:
            if((UINT)wParam == 1)
            {
                // button No.1 has been clicked, now do something
    
            }
    
    return 0; // Allways return 0(LRESULT->void)
    }

That's it! Now your button should work.


Additional member functions:

  • A function to enable/disable a button (this routine is implemented but not working on my NT4 even though it works on my XP-Home):
    BOOL CCaptionButton::EnableButton(BOOL bEnable)

Planned but not yet implemented:

  • A function to show/hide a button
  • A function to get/set the state of a button
  • ..... ..... ..... .....
  • Suggestions for more are welcome!

    These are the messages that are handled in class CCaptionButton:

    • WM_NCPAINT: This is where the button will be drawn to the caption.
    • WM_NCACTIVATE: The active/inactive state of the dialog will be "changed" here.
    • WM_NCLBUTTONDOWN: The mouse-clicks will be handled here.
    • WM_NCMOUSEMOVE: Here the button will be told when the mouse hovers over it.
    • WM_SETTEXT: This message must be handled, otherwise the caption will change in a way I don't like Wink | ;-)

    Credits

    • If you want to know more about messaging, you should read the excellent essay from Joseph M. Newcomer
    • Paul Di Lascia. I reused his code in isWindowActive(...).
    • For a Win32 implementation, look here.

    UPDATES:

    • 04.06.2004
      • TRACKMOUSEEVENT structure added
      • TrackMouseEvent(TRACKMOUSEEVENT lpEventTrack) - function added
      • Message-handling for WM_NCMOUSELEAVE added
      • changed some values in COLORADJUSTMENT structure
    • 11.06.2004
      • solved Problem for disappearing buttons on right-mouseclick in NC-area
      • solved problem for delay of drawing the buttons when dialog is re-activated by a left-mouseclick in the NC-area

    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

    Thomas Latuske
    Web Developer
    Germany Germany
    My name is Thomas, I'm born on January the 11th in
    1970, right now I'm working in the Quality department
    of a big Pipe mill as a Technician.
    My hobbies are my girl friend, my car, RC-Planes and
    Computers. I begun with VC++ some time ago and now
    Programming is like a drug to me (I'm still a
    beginner). I want to learn it all in a blink of an
    eye Wink | ;-) but i know that this is not possible. It's
    real fun for me and I do small Programms for my own
    use.
    O.K. enough written..... I need my Time to debug
    everything that crosses my way! Wink | ;-)

    Comments and Discussions

     
    GeneralCaption buttons do not appear in Windows 7 Pinmembermegraham@msn.com5-Sep-10 20:11 
    GeneralRe: Caption buttons do not appear in Windows 7 Pinmemberminregol10-Feb-11 3:07 
    GeneralRe: Caption buttons do not appear in Windows 7 PinmemberLomeo16-Sep-11 4:54 
    GeneralRe: Caption buttons do not appear in Windows 7 Pinmemberdrallons23-Feb-12 4:18 
    GeneralRe: Caption buttons do not appear in Windows 7 PinmemberkissLife28-Oct-13 16:29 
    GeneralWarning this class does not work with Windows Home Server (or Windows 2003) PinmemberLars [Large] Werner23-Jan-09 12:09 
    GeneralRe: Warning this class does not work with Windows Home Server (or Windows 2003) Pinmemberbinyo6629-Jun-09 4:28 
    QuestionTooltips? Pinmembermatt20001-Sep-06 5:37 
    Do you have any code to support tooltips?
    GeneralButton does not work after openfile dialog Pinmembercnstim14-Feb-06 13:31 
    GeneralRe: Button does not work after openfile dialog Pinmembercnstim14-Feb-06 14:03 
    GeneralWM_NCMOUSEMOVE don't work PinmemberSvetoslav Chekanov10-Aug-05 23:37 
    GeneralRe: WM_NCMOUSEMOVE don't work Pinmemberjtwang6-Jul-06 10:05 
    GeneralRemoveProp() Pinmemberx-bay8-Feb-05 4:30 
    GeneralRe: RemoveProp() PinmemberThomas Latuske9-Feb-05 6:20 
    GeneralRe: RemoveProp() PinmemberThomas Latuske9-Feb-05 6:30 
    GeneralRe: RemoveProp() Pinmemberx-bay9-Feb-05 11:50 
    GeneralA problem PinmemberPiccinano14-Nov-04 0:49 
    Generalusing menu Pinmemberslubka9-Sep-04 3:00 
    GeneralRe: using menu PinmemberThomas Latuske9-Sep-04 6:24 
    GeneralRe: using menu Pinmemberslubka13-Sep-04 20:43 
    GeneralRe: using menu Pinmemberbrushington22-Aug-07 10:40 
    GeneralRe: using menu Pinmemberbrushington22-Aug-07 21:04 
    Generalgood Pinmemberbluntman13-Jun-04 2:45 
    GeneralButtons disappear Pinmemberpullover8-Jun-04 22:59 
    GeneralRe: Buttons disappear PinmemberThomas Latuske9-Jun-04 9:04 

    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 | Mobile
    Web01 | 2.8.140721.1 | Last Updated 14 Jun 2004
    Article Copyright 2004 by Thomas Latuske
    Everything else Copyright © CodeProject, 1999-2014
    Terms of Service
    Layout: fixed | fluid