Bitmapped Command Button

All buttons begin their incarnation as a member of class Cbutton, which is derived from the class CWnd. Although this class includes Radiobuttons and Checkboxes, This perticuler Discussion will focus only on the command buttons.

All dialog box control , including command buttons, have properties and styles. Button styles are recognized by their BS_Prefix. Some of the Button styles are

BS_PUSHBUTTON
BS_RADIOBUTTON
BS_AUTORADIOBUTTON
BS_3STATE
BS_AUTOSTATE
BS_CHECKBOX
BS_AUTOCHECKBOX
BS_DEFPUSHBUTTON
BS_GROUPBOX
BS_LEFTTEXT
BS_OWNERDRAW

In above all styles we mainly concentrate on BS_OWNERDRAW for creating a Bitmapped buttons.

Avery easy way to add a touch of elegance to command button is to draw them with bitmap instead of simple text descriptions. This is not only a simple procedure but there is little penalty to be paid in terms of resource consumption. The bitmaps are loaded when needed and discarded when closed.

Using a bitmap as a face of a command button can change the perception of the application. At the heart of this technique is the class CbitmapButton. Object of this class consists of up to 4 bitmaps, corresponding to each of the possible states of a button can possess.

1. Up
2. Down
3. Focused
4. Disabled

Only the bitmap for UP is required ; the rest at the discretion of the developer. For simple "OK" and "Cancel" buttons that immediately close a dialog box when clicked, this is all that is necessary. More complex dialog boxes require some or all of the other states. E.g. the application requires the user to make a selection from a combo or list box before an action completed , then application may show OK as disabled button until such selection is made, ofcourse the cancel button should always be available.

Whenever user create any bitmap for any button , pay close attention to the border of the image, because this is use to provide visual feedback to the user regarding the state of the button.

Implementing Bitmapped Buttons
New lets see how its done. There are six main step to follow in order to use a bitmapped button in a dialog box.
  1. Draw the necessary bitmaps
  2. Create the Dialog box template , positioning the buttons where desired.
  3. Declare a resource ID and button caption.
  4. Insert bitmap reference in to your .RC file
  5. Add a CBitmapButton member object to the dialogs class.
  6. Load the bitmaps in the dialogbox;s OnInitDialog() routine.

For this Discussion , App Studio is used as the drawing tool for the bitmap in order to make it easier to discuss the associated properties , resource ID, and so on. When drawing the bitmap of the buttons strive to keep them 16X16 pixels or 16X32 pixels. However they can be any size and all are treated as the same as bitmap for the Upstate. Depending upon how your dialogbox is laid out user may have to adjust the postion of the buttons in the dialog box after testing.

While in App studio assign the button a unique ID ( e.g. ID_CANCEL ,etc.) and the BS_OWNERDRAW style. User must also assign a caption to the button, even though it will be covered by the bitmap. This is very important because this caption is related to the name of the bitmap that become the face of the button. The framework looks for the letter U, D, F and X appended to the caption of the button which signify Up, Down, Focus and Disable respectively. Lets say user give the button the caption "CANCEL". In resource file (.RC), user must have a bitmap with the ID, "CANCELU" for upstate of button, a "CANCELD" for down state of button, "CANCELF" for focus state of button and "CANCELX" for disable state of button. Thus the .RC file might contain the following declaration for the Cancel button having four states:

CANCELUBITMAP DISCARDABLE "RES\\CANCELU.BMP"
CANCELDBITMAP DISCARDABLE "RES\\CANCELD.BMP"
CANCELFBITMAP DISCARDABLE "RES\\CANCELF.BMP"
CANCELXBITMAP DISCARDABLE "RES\\CANCELX.BMP"

If suppose the ID of button on the dialog box is IDCANCEL which is default ID for cancel then user just have to create one Bitmap in that case the .RC file contain only one string like this :

CANCELUBITMAP DISCARDABLE "RES\\CANCELU.BMP"

In the same way if button id is IDOK then .RC file can have one resource entry and this is:

OKUBITMAP DISCARDABLE "RES\\OKU.BMP"

Now lets see how we can do this ::

In your project Add one dialog box with two button as show in the first diagram for button "ok" give resource ID "IDOK" and for button "cancel" give resource ID "IDCANCEL" which are default resource ID for "ok" and "Cancel".

Insert bitmap for "OKU" and "CANCELU" of size 16X32 or whatever size you want. You can also have bitmap for "OKD", "OKF", "OKX", "CANCELD","CANCEF" and "CANCELX" that up to the developer and the requirement of the application.

Now derive a class CBitmapDlg from CDialog.

The modification to the file BitmapDlg.h are shown here in bold typeface :

class CBitmapDlg : public CDialog
{
// Construction
public:
 // standard constructor
 CBitmapDlg(CWnd* pParent = NULL);   

// Dialog Data
 //{{AFX_DATA(CBitmapDlg)
 enum { IDD = IDD_BITMAPDLG };
CBitmapButton m_Cancel; CBitmapButton m_Ok;
//}}AFX_DATA // Implementation }

The last thing to do is change the OnInitDialog() routine for CBitmapDlg. It will look like this:

BOOL CBitmapDlg::OnInitDialog()
{
 m_Ok.AutoLoad(IDOK, this);
 m_Cancel.AutoLoad(IDCANCEL, this);
 // Additional statement goes here
}

Thats all there is to it. When the dialog box is activated the buttons will have the bitmaps attached. Notice that developer do not have to explicitly load each bitmap for each of the four states of the button this is handled automatically by the framework routine AutoLoad(). If you want to know what exactly this AutoLoad() routine is doing mail me I will send you the completed internal concept.

Now user can use the member routine function to activate and deactivate the buttons like:

// it will show the bitmap "OKU" on "Ok" button
m_Ok.EnableWindow(TRUE); 	

// it will show the bitmap "OKX" on "Ok" button
m_OK.EnableWindow(FALSE); 	

in this way user can have a new look to the Dialog Box.

Downloads

Download source - 46 Kb


Comments

  • ASSERT problem solution

    Posted by Legacy on 02/17/2004 12:00am

    Originally posted by: fmmanrique

    Hi,
    I have also had the assert problem with the AutoLoad function. I was just going to change this function by LoadBitmaps function when I discovered the solution to the problem:

    "If you use AutoLoad in the OnInitDialog function, you shall call it before the base class function. For example:

    BOOL CSampleDlg::OnInitDialog()
    {
    //Init the buttons
    m_bitmapButton1.AutoLoad( IDC_SAMPLE_BUTTON1, this);

    CDialog::OnInitDialog();

    //The following line generates an ASSERT ERROR!!
    m_bitmapButton2.AutoLoad( IDC_SAMPLE_BUTTON2, this);

    ...

    return TRUE;
    }

    I hope this will be helpful to somebody, BYE

    • no use

      Posted by fuxiyou on 07/26/2012 07:33am

      I try as you said ,but it didn't work

      Reply
    Reply
  • Assertion problem with Autoload

    Posted by Legacy on 09/18/2003 12:00am

    Originally posted by: Tri P.

    While waiting for any answer on the assertion problem when using Autoload, I used the LoadBitmaps function and it works fine.
    Does anyone out there know how to fix the assertion problem?

    Reply
  • I use this approach

    Posted by Legacy on 09/02/2003 12:00am

    Originally posted by: Abe

    Firstly, create two bitmaps and name them, say, IDB_MYB UTTUP and IDB_MYBUTTDWN. Then add a button to a dialog. Set it's "owner draw" and "bitmap" properties and create a control variable for it via classwizard, say, MyButtonCtrl. Then modify the dialog's class header file - change the variable's type class in AFX_DATA block from CButton to CBitmapButton. Finally, in the OnInitDialog() add MyButtonCtrl.LoadBitmaps(IDB_MYBUTTUP,IDB_MYBUTTDWN). You can eventually size the button via MyButtonCtrl.SizeToContent().

    This works ok for me.

    Abraham

    Reply
  • BS_OWNERDRAW

    Posted by Legacy on 08/21/2003 12:00am

    Originally posted by: Branco marks

    I tried your program it worked, however mine does not work i donno why. if i disable BS_OWNERDRAW then the bitmap is not drawn, and if i enable it i get an error a DEBUG ASSERtION FAILED. can ynone help me
    

    Reply
  • i waasted time

    Posted by Legacy on 01/25/2003 12:00am

    Originally posted by: jayamurugan

    waaste of time on following your procedure
    I was trying to add a bitmap to the button simply
    I really got confused . I am sorry to say this
    Once I tried thse I will send you teh simple step bystep to
    create a bitmap on the button

    bye

    Reply
  • Assertion Error...

    Posted by Legacy on 08/23/2002 12:00am

    Originally posted by: jc

    I have too assertion error, what can I do for??

    Reply
  • Assertion Error!!

    Posted by Legacy on 07/29/2002 12:00am

    Originally posted by: Anthony

    When my code gets to the line:

    ASSERT(m_bitmap.m_hObject != NULL); // required

    in the DrawItem member fundtion of the CBitmapButton class it asserts! I have read and reread your article and have looked at some examples in MSDN and I cannot figure out why I have this problem! Also, when AutoLoad tries to load my bitmaps, it is not successful. I have labeled my bitmap "AGAINU", including the quotes (the VC++ documentation said I had to). Please help!!

    Reply
  • How can I do?

    Posted by Legacy on 12/11/2001 12:00am

    Originally posted by: swallow

    I have three Bitmaps:up,Focused,Down.
    When the Mouse is over the button ,I want the Bitmap is the Focused,when the Mouse leave,the Bitmap is the up,and when clicking the button,the Bitmap is the Down.
    How can I do?

    Reply
  • Here is how you can dynamically set the picture.

    Posted by Legacy on 12/04/2001 12:00am

    Originally posted by: Alex

    Here is the code I found in MSDN. The function you are
    
    interested in the most here is the LoadBitmaps function.
    It takes several arguments that correspond to the UP, DOWN,
    FOCUS, and DISABLE pictures.

    CBitmapButton myButton;

    // Create the bitmap button (must include the BS_OWNERDRAW style).
    myButton.Create(NULL, WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,
    CRect(10,10,100,100), pParentWnd, 1);

    // Load the bitmaps for the button.
    myButton.LoadBitmaps(IDB_UP, IDB_DOWN, IDB_FOCUS, IDB_DISABLE);

    // You'll need to call the Invalidate function in order
    // to update the GUI immediately.
    myButton.Invalidate(TRUE);


    Hope this is as easy to understand as this original sample.

    Reply
  • Very Good and Precise

    Posted by Legacy on 10/11/2001 12:00am

    Originally posted by: Arun Kumar Goyal

    This a very important and good feature, which you have explained so easily. I have implemented this in my all projects.
    Once again I say it is nice.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: August 14, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Data protection has long been considered "overhead" by many organizations in the past, many chalking it up to an insurance policy or an extended warranty you may never use. The realities of today makes data protection a must-have, as we live in a data-driven society -- the digital assets we create, share, and collaborate with others on must be managed and protected for many purposes. Check out this upcoming eSeminar and join Seagate Cloud …

  • Corporate e-Learning technology has a long and diverse pedigree. As far back as the 1980s, companies were adopting computer-based training to supplement traditional classroom activities. More recently, rich web-based applications have added streaming audio and video, real-time collaboration and other new tools to the e-Learning mix. At the same time, the growing availability of informal learning tools--a category that includes everything from web searches to social media posts--are having a major impact on …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds