Virtual Developer Workshop: Containerized Development with Docker

Click here for a larger image.

Environment: Visual Studio .NET, can be used with VC++ 6 with minor changes (for-loop scoping)

I've been working on a project that can be pretty UI-intensive. And, because it's a graphical environment (a 3D modeller), it only makes sense that the UI be graphically well designed. One of the UI elements that I'm particularly pleased with was the hover buttons.

I really didn't feel like creating a bunch of icons for each button (standard, hovering, clicked, checked, disabled, and so forth), so I decided to create a class that would "render" buttons rather than just plop them on the screen. The result is the buttons you see above. Each button is rendered from a single bitmap. All effects (shadow, disabled transparency, and so on) are automatically generated, rendered, and blended into the window by using the included code. You supply one bitmap image, and the UIButton class takes care of the rest for you. Your artists had better treat you to a free lunch for this one.

The button class itself is pretty simple to work with. However, to accomplish the rendering tasks, you (or your art staff) will need to provide the button with a 4-channel bitmap. This is an ARGB bitmap, where the first channel is the alpha channel. Here is an example:

I used Photoshop to generate these images, though I'm sure plenty of other lesser-expensive applications provide alpha-channel support. If you have access to Photoshop, I've included the master artwork for the sample icons in PSD format with the project source. Simply load these images and save them as RAW files.

The format you choose is up to you because you'll be passing in a memory buffer for the bitmap. I chose to use RAW files, which are simply the image pixels laid out in linear format (four bytes per pixel) without any header information.

The buttons also can automatically re-size themselves to half-sized (small) icons. This is done by using a box-filter, so the smaller image is created by blending pixels together, rather than simply removing them; this produces a nice-looking, reduced-size image. Optionally, you can set the buttons to display as text only. Each of these settings (including the bitmap itself) can be changed on the fly and the button can be told to resize itself automatically for its new icon.

The use of the alpha channel has a few other benefits, and the UIButton class takes advantage of them. First, an alpha channel can contain soft edges, which means that the buttons can be blended onto the window with antialiasing (no more jaggies). Also, the buttons can have holes in the artwork that allow you to see through to the window or shadow below, giving them a true sense of depth. The buttons can even be semi-transparent. And finally, the alpha channel is used to render the drop-shadow, so any soft and subtle details contained in the alpha channel will also be contributed to rendering the drop shadow.

Using the buttons is pretty simple... here's an example:

Automatic Soft Edges and Shadow Generation

  // For check-box like buttons, simply enable the dual-state flag,
  // like so:

  button.dualState() = true;

  // We'll need to load up the 4-channel (ARGB) image file.
  // The code to do this for RAW-format files is included with the
  // project. I use RAW files because they're simple to read (just
  // an array of DWORD values, one per pixel; no header
  // information).

  button.bitmap() = bitmapData;

  // Tooltip?

  button.tip() = "tip goes here";

  // If it's a text button, set the label

  button.label() = "OK";

  // For text buttons, turn this flag on...

  button.textOnly() = true;

  // Set the size of the button: LargeIcons or SmallIcons

button.iconSize() = UIButton::LargeIcons;

Because the buttons are derived from CButton, that's really all there is to it. For the full details on how to use the UIButton class, check out the project source.


Download demo project - 113 Kb
Download source - 246 Kb


  • transparency bugfix

    Posted by phaetone on 09/01/2005 10:44am

    file UIButton.cpp
    // Fill the buffer with the background color
    memset(frameBuffer, backgroundRGB, sz * sizeof(unsigned int));
    // Fill the buffer with the background color
    for (unsigned int ii = 0; ii < sz; ii++)
    	frameBuffer[ii] = backgroundRGB;
    That's all!

  • Good One. But not really transparent

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

    Originally posted by: Hugo

    Good work Paul.

    But I found a problem, why background isn't really transparent?


  • How to scale Images

    Posted by Legacy on 11/20/2002 08:00am

    Originally posted by: Meghna Trivedi

    How to scale the image according to the static control?
    How to decrease the frame time to load a image?

  • Very Nice

    Posted by Legacy on 10/02/2002 07:00am

    Originally posted by: Old Timer

    I know just where to use this!


  • Wow

    Posted by Legacy on 10/01/2002 07:00am

    Originally posted by: Thoemmi


    IMHO the only issue regards the check-box style: If you move your mouse over such a button, you cannot see whether it is checked or not.

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date