Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

XAnalogClock - a skinnable analog clock

0.00/5 (No votes)
20 Jul 2006 1  
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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here