Windows includes international support. The WIN.INI file created during installation of Windows contains a section headed [intl]. This lists information concerning formats of dates, time, currency, and numbers. You can display dates in one of three different formats: month-day-year, year-month-day, or day-month-year. The separator between these three numbers can be a slash, a dash, a period, or, in fact, any character you like. You can display the time in either 12-hour or 24-hour format; a semicolon or a period is commonly used to separate hours, minutes, and seconds.
The SetInternational function in DIGCLOCK retrieves this formatting information from the WIN.INI file by using the Windows GetProfileInt (for integers) and GetProfileString (for strings). These calls must include default values if Windows cannot find the values in WIN.INI. SetInternational stores the values in global variables that have the same names as the text strings that identify them in WIN.INI. The WndPaint function uses the values obtained from WIN.INI to format the date and time displays and then calls DrawText to center the two lines of text within the window.
As you would expect, whenever DIGCLOCK's window procedure receives a WM_TIMER message, it invalidates the window to generate a WM_PAINT message. But WndProc also invalidates the window when it receives a WM_WININICHANGE message. Any application that changes WIN.INI sends the WM_WININICHANGE message to all active Windows applications. If the [intl] section of WIN.INI is changed, DIGCLOCK will know and will obtain the new international information. To see how this works, load DIGCLOCK, load the CONTROL PANEL program included with Windows, select Country Settings from the Preferences menu, and change either the date format, the date separator, the time format, or the time separator. Now press Enter. The Control Panel updates the WIN.INI file, and DIGCLOCK's display reflects that change—Windows' message magic at work.
When the window procedure receives a WM_WININICHANGE message, it invalidates the window using:
InvalidateRect (hwnd, NULL, TRUE) ;
When DIGCLOCK receives a WM_TIMER message, it invalidates the window using:
InvalidateRect (hwnd, NULL, FALSE) ;
A value of TRUE in the last parameter tells Windows to erase the background before drawing the window. A value of FALSE tells Windows simply to draw over the existing background. We use FALSE when processing WM_TIMER messages because this approach reduces flickering of the display. You may be wondering why we need to use the TRUE value at all.
A TRUE value is necessary when processing WM_WININICHANGE messages because the length of the displayed strings can change by several characters if you switch the time format from 12 hours to 24 hours. However, the largest change that occurs as a result of a WM_TIMER message is two characters—for instance, when the date advances from 12/31/87 to 1/1/88—and the formatted string that WndPaint uses for the display has a couple of blanks on each end to account for this change in length and the proportional font.
We could also have DIGCLOCK process WM_TIMECHANGE messages, which notify applications of changes to the system date or time. Because DIGCLOCK is updated every second by WM_TIMER messages this is unnecessary. Processing WM_TIMECHANGE messages would make more sense for a clock that was updated every minute.