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

World Time

0.00/5 (No votes)
14 Mar 2004 1  
Displays current time in various timezones. Also demonstrates some Win32 API programming tricks.

Sample Image - WorldTime.jpg

Introduction

This application runs as an icon in the system tray and displays the current time in different parts of the world. A tooltip also shows the current time in the place which is set as the default.

The idea of making this application came to me when I started work here in Japan. I come from India and everytime I needed to contact somebody back home, maybe by telephone or by chat, I had to first find out what time it was there. I found it to be annoying to always subtract 3.5 hours from the current Japan time (And I always got it wrong). When I first created this application, it showed only the current time in India. I called the program 'India Time' then. That's when I thought of changing it to 'World Time'.

Since this application didn't require any window to be displayed, I decided on a windows application (Not using MFC). I didn't want it to include classes like CMainFrame or any CView derivatives which I'm not going to use. A registry class in included, which uses the stl vector class for enumeration.

For most of us, the code of a windows application is a real chaos, where functions span thousands of lines with big switch statements. With the help of the code in this article I would also like to share some tips that most people programming using Win32 APIs do not do. Following these rules should get you out of the nightmare of programming using only the Win32 API.

Something about the demo program

The program creates an overlapped window which is never displayed (I call this a hidden window) and a tray icon. The popup menu to be displayed when the tray icon is right clicked is created dynamically. Initially, when the popup menu is created, some items like 'Exit', 'Add Timezone' and a couple of separators are inserted into the menu. Many timezone information are stored in the registry. This information is read, loaded and sorted into a vector at startup. When the user right clicks the tray icon to display the popup menu, the timezone information is taken from the vector and the corresponding time is calculated with respect to the current system time. These times are then added to the popup menu before it is displayed.

There is an option in the popup menu called 'Add Timezone'. Using this the user can add a new timezone. I have currently not given any options for deleting or modifying a timezone. But that can be easily done by extending the 'Add Timezone' dialog. The dialog box accepts the name of the place and the difference in time from the Greenwich Mean Time (GMT). On Clicking the 'Set' button, this information is added to the registry and the menu.

Add Timezone Dialog

One of the timezones in the menu can be set as the default timezone by clicking on it. What this means is that it will be shown as a tooltip of the tray icon.

Using the code

Here a brief description of the projects files and their contents

Stdafx.h Includes the windows and C runtime header files.
Registry.h Class declaration of the CRegistry class.
Registry.cpp Implementaion of the CRegistry class.
WorldTime.h Contains a few #define values and function prototypes.
WorldTime.cpp Main code of the application which contains the WinMain function.
WndFunc.h Function prototypes dealing with the main hidden window and the tray icon.
WndFunc.cpp Function definitions of the above mentioned functions.
DlgFunc.h Function prototypes dealing with the 'Add Timezone' dialog box.
DlgFunc.cpp Function definitions of the above mentioned functions.

Most programmers would write this propram without using the WndFunc and DlgFunc files. The whole program will usually be written in the WorldTime.cpp file, which will eventually not be an easy ride to maintain. What I have done here is to logically group functionality dealing with the tray icon and the dialog box into separate files. Using this technique, the switch statements in the main file becomes very simple.

Here is the switch statement of the procedure dealing with the dialog box messages.

LRESULT CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message) 
    {
    case WM_INITDIALOG:
        DlgFunc::OnInitDialog(hDlg, message, wParam, lParam);
        break;

    case WM_COMMAND:
        DlgFunc::OnCommand(hDlg, message, wParam, lParam);
        break;

    case WM_NOTIFY:
        DlgFunc::OnNotify(hDlg, message, wParam, lParam);
        break;
    }

    return 0;
}

Here each message received is delegated to a function, thereby giving it an MFC feel. You will also notice the use of namespaces (DlgFunc::), which makes it possible to have functions with the same name in different files. The DlgFunc.h and Wndfunc.h files have the function prototypes declared within a namespace. In this code, both the WndFunc and DlgFunc namespaces have the same OnCommand function. Another thing to notice here is that each delegate function in the switch statement has the same signature. This way it would be possible to completely eliminate the switch statement by using function pointers or pointer-to-member operators (.* and ->*).

Something more about the code

Now lets look at some things worth mentioning in the code.

The Registry.h file has a VALUES structure used while enumerating registry values. The structure contains a union of a character array and a dword, because a registry value can only either be a string or a dword or a binary value. The class currently does not support binary values.

The VALUES structure has an overloaded < (less than) operator defined. This is used by the STL sort algorithm to sort the contents of the vector.

To change the registry path for storing timezones, change the REG_KEY #define constant in the WorldTime.h file.

The ShowPopupMenu function in the WndFunc.cpp file is called whenever the user right clicks on the tray icon. This function first deletes all place entries from the menu and then adds them back after calculating the current time.

The GetZoneTime function in the WndFunc.cpp file returns the formatted time based on the passed in bias information stored in the registry. The actual time calculation is done using the SystemTimeToTzSpecificLocalTime API which takes the timezone information and the Greenwich Mean Time as input parameters and returns the specific local time. The GetSystemTime API gives the GMT based on the system time.

The OnTimer function in the WndFunc.cpp file is called by a timer to change the tooltip of the tray icon. When the application is started or when the user changes the default timezone, a timer of 10 milliseconds interval is set. This timer event is deleted within the OnTimer function and a new timer of 1 minute interval is set.

I guess there is nothing worth mentioning in the DlgFunc.cpp file, but the controls accepting timezone information are list boxes whose values are changed depending on the notification sent by the updown control (spin button). And also the items in the list boxes are selected when they get focus and deselected when they loose focus.

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