Friday, July 25, 2008

How to draw gradient buttons

A few years ago, I wrote an MFC PocketPC Numeric Key Pad control (a dialog, actually) to help with numeric input on the Pocket PC. Recently I had to convert this code to WTL for a Windows CE 5.0 application and I decided to try and give it a modern look (see picture). This was something I was keen on doing because it was a bit of a mystery to me how that effect was achieved.

It's no big deal after all. Each button is painted with two gradients of gray and the digits are painted with a ClearType-rendered bold Tahoma font. The code to create the button effect (what do you call it: chiseled?) is very simple:

TRIVERTEX vertex[4] = { 0 };
GRADIENT_RECT grRect[2] = { 0 };
int nHeight2 = m_rc.Height() / 2;

This declares the variables we need to draw the button, where m_rc contains the button rectangle coordinates. Now we need to give the gradient renderer the information on how to render the button. Each button is split into two gradient-filled rectangles that must be described by their top left and bottom right points and color information. The top rectangle is:

vertex[0].x = m_rc.left;
vertex[0].y =;
vertex[0].Red = 0x0000;
vertex[0].Green = 0x0000;
vertex[0].Blue = 0xb000;

vertex[1].x = m_rc.right;
vertex[1].y = + nHeight2;
vertex[1].Red = 0x0000;
vertex[1].Green = 0x0000;
vertex[1].Blue = 0x7000;
vertex[1].Alpha = 0x0000;

Note how the color components are encoded. Now, we describe the bottom rectangle:

vertex[2].x = m_rc.left;
vertex[2].y = + nHeight2;

vertex[2].Red = 0x0000;
vertex[2].Green = 0x0000;
vertex[2].Blue = 0x2000;
vertex[2].Alpha = 0x0000;

vertex[3].x = m_rc.right;
vertex[3].y = m_rc.bottom;
vertex[3].Red = 0x0000;
vertex[3].Green = 0x0000;
vertex[3].Blue = 0x7000;
vertex[3].Alpha = 0x0000;

Finally, we must group these together for the API call:

grRect[0].UpperLeft = 0;
grRect[0].LowerRight = 1;
grRect[1].UpperLeft = 2;
grRect[1].LowerRight = 3;

GradientFill(dc, vertex, 4, (PVOID)grRect, 2, GRADIENT_FILL_RECT_V);

You may want to try different colors and shades to fit your taste.

No comments: