Download sample project and source files Yes – I know there is already a topic on circular push buttons but they weren’t quite what I wanted, so I wrote my own. What I wanted was a button that looked exactly like the normal buttons, but instead I wanted them circular. First of all I make […]
CodeGuru content and product recommendations are
editorially independent. We may make money when you click on links
to our partners.
Learn More

Download sample project and source files
Yes – I know there is already a topic on
circular push buttons but they weren’t quite what I wanted, so
I wrote my own. What I wanted was a button that looked exactly like
the normal buttons, but instead I wanted them circular.
First of all I make sure the buttons are circles (and not ellipses)
and store the centre and radius of the button. Next I simply make the
button owner drawn and draw it like every other owner drwn button, but
instead of being able to use nice routines like Draw3dRect, I had to
roll my own circle drawing routine which would draw each pixel with the
correct colour dependant on the point on the circle I was drawing.
I will not include the full source in this page – it is available for
download here. The owner draw part is simple
and follows along the lines of any other owner drawn button. The circle
drawing routine is a standard algorithm, with the only modification in
calculating the pixel colour. Given two colours crBright and crDark, and
an angle relative to the x-axis, the colour for a pixel can be calculated
using the following.
COLORREF GetColour(double dAngle, COLORREF crBright, COLORREF crDark)
{
#define Rad2Deg 180.0/3.1415
#define LIGHT_SOURCE_ANGLE -2.356
ASSERT(dAngle > -3.1416 && dAngle < 3.1416);
double dAngleDifference = LIGHT_SOURCE_ANGLE - dAngle;
if (dAngleDifference < -3.1415) dAngleDifference = 6.293 + dAngleDifference;
else if (dAngleDifference > 3.1415) dAngleDifference = 6.293 - dAngleDifference;
double Weight = 0.5*(cos(dAngleDifference)+1.0);
BYTE Red = (BYTE) (Weight*GetRValue(crBright) + (1.0-Weight)*GetRValue(crDark));
BYTE Green = (BYTE) (Weight*GetGValue(crBright) + (1.0-Weight)*GetGValue(crDark));
BYTE Blue = (BYTE) (Weight*GetBValue(crBright) + (1.0-Weight)*GetBValue(crDark));
return RGB(Red, Green, Blue);
}
This is a simple linear interpolation between the two colours based on the cosine
of the angle between the light source and the point. Angles are measured from the +ve
x-axis (i.e. (1,0) = 0 degrees, (0,1) = 90 degrees ), but remember: positive y points down!