Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / WTL
Article

CCaptionButton - Add Buttons on the Caption Bar

Rate me:
Please Sign up or sign in to vote.
4.96/5 (24 votes)
19 Sep 20054 min read 135.2K   5.3K   69   9
A reusable WTL base class to add buttons on the caption bar.

Introduction

After creating the CAppBar class, I was hoping to add a button on the caption bar, right next to the Close button to control the autohide attribute of the AppBar window. To add a button on the caption bar is not as easy as adding normal buttons on the client area. There are some existing applications with a custom button on the caption bar. But we can hardly find the code to implement that (not to say reusable code). So, I decided to create one. That’s CCaptionButton.

To add a normal window-based button on the caption bar is simply impossible. Those that appear as caption buttons are drawn on the caption bar with a look and feel of the normal buttons. Handling of WM_NCPAINT message is the main method to achieve that. Of course, other messages like mouse movement should also be handled to achieve real button look and feel.

Prepare images

Since we need to draw the button on the caption, we need to prepare some images to simulate the button. The CCaptionButton class requires an image list for each button containing the following images:

  • Normal status
  • Pushed status
  • Hover status
  • Checked status (optional)
  • Disabled status (optional)

The above list is enough for understanding what is what. Here is a sample image to create an image list for our push pin caption button:

Add caption buttons

We have to support multiple caption buttons for one window. Each button is stored internally with the following data structure:

struct    _button
{
    UINT        uID;        //command ID
    int        cx;          //width
    int        cy;          //height
    HIMAGELIST    himl;     //image list
    UINT        uStatus;    //status (image index)
    char        szHint[80]; //tooltip text
};

A vector is used to hold the buttons internally. To add a button, simply call:

int AddButton(UINT uID, int cx, int cy, 
       HIMAGELIST himl, LPCTSTR lpszHint=NULL);

where

  • uID is the command ID of the button. When the button is clicked, a WM_COMMAND message with a uID parameter is sent to the window. So, handling a caption button clicking is just the same as handling a normal button clicking.
  • cx and cy specify the size of the button. This size must match the size of the images in the corresponding image list.
  • himl holds all the images required to draw the button. It must contain at least three images with the correct order as described previously or up to five images if checked and disabled status is required.
  • lpszHint is the tooltip text for the button.

Positioning

Where do we draw these buttons? Auto positioning sounds like a must for a reusable class. However, I found it impossible to put the button at the right place in all window styles.

  • Is the window a tool window, which has a relatively thin caption bar?
  • Dose the window contain a minimize button?
  • Dose the window contain a maximize button?
  • Dose the window contain a help button?

All these will make auto positioning a mess. Finally, I decided to let the derived class position the buttons. The function GetButtonPos is designed to be overridden to provide positions for each button.

POINT GetButtonPos(int index);

The CCaptionButton class provides a default implementation of GetButtonPos. But it assumes that the target window is a tool window, and that there are no existing system buttons. For any other style, you have to implement your own GetButtonPos to position the buttons correctly. By providing a customized GetButtonPos function, the button positioning becomes more powerful and flexible than auto positioning. You can even stack two buttons vertically, as in the demo application.

Usage

CCaptionButton class can be easily added to any ATL/WTL window class that is derived from CWindowImpl directly or indirectly. To conclude the usage:

  1. Use CCaptionButton class as the base class.
  2. Use CHAIN_MSG_MAP to chain messages to CCaptionButton class.
  3. Call AddButton to add one or more buttons to the caption bar.
  4. (Important) Override the GetButtonPos function to provide positions for each button added.
  5. Handle the WM_COMMAND notification sent by the caption button in the same way as handling a normal button click.
  6. (Optional) Call CheckButton to change the checked status of the caption button.
  7. (Optional) Call EnableButton to change the enable status of the caption button.

Features

  • Add one or more buttons to the caption bar.
  • Flexible positioning.
  • WM_COMMAND support for button clicking.
  • Tooltip support.

Sample application

The attached sample application demonstrates the usage of CCaptionButton. The CAppBar class is also used for AppBar functionality. To get more details on CAppBar, check here. Five caption buttons are used in the sample. The pushpin button controls the auto hide attribute of the AppBar window; four other buttons dock the window to the four edges of the screen; and the "Dock bottom" button is disabled, so that you can see how a disabled button would look like.

Enjoy

Well, the code and the sample project are attached. I hope it would be easy to use and simple to read. I also hope some day it would be part of WTL. I was using Visual Studio 2003 and WTL7.5 while writing this code. I did not test it in any other platform. I hope it works well. If it doesn't, send me a message. I'll try to make it better.

Chinese readers, you can check my blog in Chinese. The Chinese version of this article is available here.

Revision

  • September 21st, 2005 - Fixed the repaint issue for classic window themes.

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


Written By
China China
I'm a chinese programer living in Shanghai, currently working for a software company whose main business is to deliver computer based testing. Software simulation for computer based testing and certifications is my main responsibility in this company. Execpt for software development, I like out-door activities and photography. I am willing to make friends in China and all over the world, so contact me if you have anything in common with meSmile | :)

Comments and Discussions

 
GeneralDoesn't work in Windows 7 Pin
masteryoda2120-Sep-10 7:09
masteryoda2120-Sep-10 7:09 
GeneralRe: Doesn't work in Windows 7 Pin
kissLife28-Oct-13 16:25
kissLife28-Oct-13 16:25 
Questioncan you help me Pin
Kingle Zhuang25-Jun-08 2:58
Kingle Zhuang25-Jun-08 2:58 
GeneralButtons on caption bar are not visible on Vista OS. PinPopular
Paresh Chitte9-Jul-07 20:46
Paresh Chitte9-Jul-07 20:46 
Hi Neil,

I am using the Vista OS and I could not able to see the buttons on Caption bar. However, if I switch the theme to "Windows Classic", then I could see the buttons on the caption bar.

Could you please help me out in rectifying this bug ?

Regards,

Paresh.
General"Tool Window" set to false and have problem Pin
Amit220329-Dec-06 8:19
Amit220329-Dec-06 8:19 
GeneralTitle and button Pin
Igor Vigdorchik13-Nov-05 6:03
Igor Vigdorchik13-Nov-05 6:03 
GeneralRe: Title and button Pin
Neil Yao13-Nov-05 14:36
Neil Yao13-Nov-05 14:36 
GeneralWhile dragging Pin
Mingliang Zhu29-Sep-05 22:09
Mingliang Zhu29-Sep-05 22:09 
GeneralRe: While dragging Pin
Neil Yao6-Oct-05 16:08
Neil Yao6-Oct-05 16:08 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.