Click here to Skip to main content
15,861,168 members
Articles / Desktop Programming / MFC
Article

XAnalogClock - a skinnable analog clock

Rate me:
Please Sign up or sign in to vote.
4.94/5 (61 votes)
20 Jul 2006CPOL5 min read 172.8K   3K   104   30
XAnalogClock displays a nice-looking skinnable analog clock in a small memory footprint.

Introduction

There are several nice implementations of digital clocks available on CodeProject and other sites, but good-looking analog clocks are harder to find. The typical analog clock you will see looks like:

screenshot

Even the Microsoft XP Date and Time dialog displays a flat 2D clock:

screenshot

There are some good-looking analog clocks. I found these in my search:

screenshot screenshot screenshot

Unfortunately, all of these last three have drawbacks: use of Flash, or dependence on a large-footprint "skinning" engine, or tight integration with a "widget" framework (also large footprint). And, of course, the source code is not available.

At this point I began thinking about what is actually involved in displaying an analog clock. It seemed to me that there were two basic problems: first, display the clock face. To achieve realistic shading and lighting effects, it was obvious that starting with a bitmap of a clock face was the easiest solution. Second, display the second, minute, and hour hands. This turned out to be the most time-consuming task. I wanted hands that came to a point for minute and hour hands, and I knew that I would have to do some kind of anti-aliasing on edges of the hands - rotating a line in a 360° range is sure to produce jaggies. I very quickly found a solution to this problem in the CodeProject article Antialiasing: Wu Algorithm, which shows how to draw anti-aliased lines.

Demo App

This is what the XAnalogClock looks like:

screenshotscreenshot
Blue SkinSilver Skin

The date and second hand are optional, and will be added (or removed) the next time the Run button is clicked after the options are changed.

How To Use XAnalogClock

To integrate XAnalogClock into your app, you first need to add the following files to your project:

  • XAnalogClock.cpp
  • XAnalogClock.h
  • CDCBuffer.h
  • WuLine.cpp
  • WuLine.h
  • clockface.bmp - see section on skinning XAnalogClock
  • date.bmp - see section on skinning XAnalogClock

Then use resource editor to add a static control to your dialog, and use the Class Wizard to attach a member variable to that control.

Next, include the header file XAnalogClock.h in the dialog's header file. Then replace the CStatic definition with CXAnalogClock.

The final step is to include msimg32.lib for linker (this is needed for the TransparentBlt() function). Go to Project | Settings, select All Configurations in the combo box at left, select the Link tab, and enter msimg32.lib in the Object/library modules entry field:

screenshot

Now you are ready to start using XAnalogClock.

Here is some code from XAnalogClockTestDlg.cpp, that shows how to use the clock:

// set resource IDs
m_Clock.SetBitmaps(IDB_BLUE_CLOCK_FACE, IDB_BLUE_DATE);

// set control size
CSize size = m_Clock.GetWindowSize();

CRect rect;
m_Clock.GetWindowRect(&rect);
ScreenToClient(&rect);
rect.right = rect.left + size.cx;
rect.bottom = rect.top + size.cy;
m_Clock.MoveWindow(&rect);

// start the clock
m_Clock.Run();

Skinning XAnalogClock

Skinning XAnalogClock is accomplished by two bmp files, clockface.bmp and date.bmp. (The file names can be anything you want - just import two bmp files using the resource editor, and assign resource IDs). In demo project, two skins are provided - "blue" and "silver".

Note - since XAnalogClock bitmap files use 24-bit (True Color), the clock might not display well if your screen color depth is set to 256 colors.

The demo file blue clockface.bmp contains bitmap for clock face:

screenshot

The clock face bitmap must be 100x100.

The demo file blue date.bmp contains a bitmap for date box (image has been enlarged):

screenshot

The date box bitmap must be 18x14.

XAnalogClock Implementation

Since XAnalogClock is based on bitmaps, it was important to provide efficient bitmap handling and display. One way I did this was by using the CDCBuffer class, which handles loading and buffering bitmaps, and speeds up display of frequently-used bitmaps.

A second optimization technique was driven by the rather obvious observation that the date, minute hand, and hour hand do not change unless the minute changes. So, for 59 out of 60 seconds, the only thing being updated on the display is the second hand. This results in a huge reduction in the CPU cycles required for processing and displaying the Wu lines. Within each minute, the current clock face CDC is saved (including the minute and hour hands), and is simply BLT'd to the display CDC when a paint occurs. Then the second hand is BLT'd to the display CDC on top of this saved CDC.

XAnalogClock Functions

Here are the functions available on CXAnalogClock:

GetTime() Get currently displayed time
GetWindowSize() Get control size
IsClockRunning() Get run state of clock
SetBackgroundColor() Set background color
SetBitmaps() Set bitmap resource IDs
SetGmtAdjust() Not currently used
SetHourHandColor() Set color of hour hand; default is black
SetMinuteHandColor() Set color of minute hand; default is black
SetSecondHandColor() Set color of second hand; default is cardinal
SetTime() Set starting time; used only when UseSystemTime() is called with FALSE
SetTransparentColor() Set transparent color
ShowDate() Show/hide date
ShowSecondHand() Show/hide second hand
Run() Start the clock
Stop() Stop the clock
UseSystemTime() Use system time; if parameter is FALSE, the time specified by SetTime() will be used

Acknowledgments

Revision History

Version 1.1 - 2006 July 20

  • Updated article to include link instructions for msimg32.lib (no source code changes).

Version 1.0 - 2006 March 23

  • Initial public release.

Usage

This software is released into the public domain. You are free to use it in any way you like, except that you may not sell this source code. If you modify it or extend it, please consider posting the new code here for everyone to share. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.



License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions

 
GeneralMy vote of 4 Pin
tanggc25-Jul-10 20:28
tanggc25-Jul-10 20:28 
GeneralError while compiling Pin
Sachin Gorade30-Apr-08 19:13
Sachin Gorade30-Apr-08 19:13 
QuestionHow to add a static control? Pin
Export3-Mar-08 11:21
Export3-Mar-08 11:21 
QuestionHelp me ! ? Pin
MacGadger20-Jul-06 18:35
MacGadger20-Jul-06 18:35 
AnswerRe: Help me ! ? Pin
Go_Ram13-Mar-09 5:15
Go_Ram13-Mar-09 5:15 
JokeRe: Help me ! ? Pin
Dario Solera13-Mar-09 5:38
Dario Solera13-Mar-09 5:38 
GeneralRe: Help me ! ? Pin
#realJSOP13-Mar-09 6:14
mve#realJSOP13-Mar-09 6:14 
GeneralRe: Help me ! ? Pin
peterchen13-Mar-09 23:55
peterchen13-Mar-09 23:55 
GeneralRe: Help me ! ? Pin
Pete O'Hanlon13-Mar-09 9:43
subeditorPete O'Hanlon13-Mar-09 9:43 
GeneralRe: Help me ! ? Pin
_Maxxx_15-Mar-09 16:36
professional_Maxxx_15-Mar-09 16:36 
Generalwow.!!! amazing!~! gr8!!! Pin
MacGadger20-Jul-06 5:31
MacGadger20-Jul-06 5:31 
GeneralLinker errors, Visual Studio 6.0 Pin
mcv99920-Jul-06 2:07
mcv99920-Jul-06 2:07 
GeneralRe: Linker errors, Visual Studio 6.0 Pin
Hans Dietrich20-Jul-06 3:25
mentorHans Dietrich20-Jul-06 3:25 
GeneralRe: Linker errors, Visual Studio 6.0 Pin
mcv99920-Jul-06 22:32
mcv99920-Jul-06 22:32 
GeneralRe: Linker errors, Visual Studio 6.0 Pin
tanggc25-Jul-10 20:36
tanggc25-Jul-10 20:36 
GeneralNo no no ! Pin
mcv99919-Jul-06 5:45
mcv99919-Jul-06 5:45 
GeneralRe: No no no ! Pin
Wes Aday19-Jul-06 5:55
professionalWes Aday19-Jul-06 5:55 
GeneralRe: No no no ! Pin
mcv99920-Jul-06 0:04
mcv99920-Jul-06 0:04 
GeneralRe: No no no ! Pin
Hamed Musavi20-Jul-06 15:22
Hamed Musavi20-Jul-06 15:22 
GeneralA complaint ... Pin
Graham Shanks5-Jun-06 11:51
Graham Shanks5-Jun-06 11:51 
Questionc# version? Pin
temp55564-Apr-06 20:54
temp55564-Apr-06 20:54 
GeneralSo nice ! Pin
$icK$29-Mar-06 2:00
$icK$29-Mar-06 2:00 
GeneralLinker error(CVT1100) with VS 2005 Pin
arjinder28-Mar-06 15:19
arjinder28-Mar-06 15:19 
GeneralRe: Linker error(CVT1100) with VS 2005 Pin
rite7-Jun-06 10:33
rite7-Jun-06 10:33 
GeneralRe: Linker error(CVT1100) with VS 2005 Pin
mceros26-Nov-08 0:58
mceros26-Nov-08 0:58 

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.