|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Subclassing Routines WM_TIMECHANGE: Detect System Changes to the Date/Time |
||
Posted: | Tuesday June 8, 1999 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB5, VB6 | |
Developed with: | VB6, Windows 98 | |
OS restrictions: | None | |
Author: | VBnet - Randy Birch | |
Related: |
SetLocaleInfo: Change System Long and Short Date Formats WM_TIMECHANGE: Detect System Changes to the Date/Time RegQueryValueEx: Identify Time Zones by Time Zone Bias EnumDateFormats: Regional Locale Date Settings EnumTimeFormats: Regional Locale Time Settings GetLocaleInfo: Regional Locale Date Settings |
|
Prerequisites |
VB5 or VB6. |
|
When
the Control Panel's Date/Time property dialog "Apply" or "OK" button is pressed, Windows broadcasts a message to all
applications notifying them of the change to the system. By subclassing a form and trapping the WM_TIMECHANGE message, a VB application
can receive this notification to make whatever adjustments are needed. An application should return zero if it processes this message.
(Note that changes made through the DOS or CMD window are not detected.)
In addition, MSDN states that applications (subject to operating system version) can use the WM_TIMECHANGE message to notify other applications that a Date/Time change has been made. To send the WM_TIMECHANGE message to all top-level windows, an application can use the SendMessage function with the hwnd parameter set to HWND_TOPMOST. The application should post the WM_TIMECHANGE message with both the wParam and lParam members passed as zero. The course to take when posting a change notification differs with the operating system version:
|
BAS Module Code |
Place the following code into the general declarations area of a bas module: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public defWindowProc As Long Public Const GWL_WNDPROC As Long = (-4) Public Const WM_TIMECHANGE = &H1E Public Declare Function SetWindowLong Lib "user32" _ Alias "SetWindowLongA" _ (ByVal hwnd As Long, _ ByVal nIndex As Long, _ ByVal dwNewLong As Long) As Long Public Declare Function CallWindowProc Lib "user32" _ Alias "CallWindowProcA" _ (ByVal lpPrevWndFunc As Long, _ ByVal hwnd As Long, _ ByVal uMsg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Public Sub SubClass(hwnd As Long) 'assign window message procedure (WindowProc) On Error Resume Next defWindowProc = SetWindowLong(hwnd, _ GWL_WNDPROC, _ AddressOf WindowProc) End Sub Public Sub UnSubClass(hwnd As Long) 'restore the default message handling before exiting If defWindowProc Then SetWindowLong hwnd, GWL_WNDPROC, defWindowProc defWindowProc = 0 End If End Sub Public Function WindowProc(ByVal hwnd As Long, _ ByVal uMsg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long 'window message procedure On Error Resume Next Select Case hwnd 'If the handle returned is to our form, 'perform form-specific message handling 'to deal with the notifications. Case Form1.hwnd 'form-specific handler Select Case uMsg Case WM_TIMECHANGE 'take some action if desired Form1.Caption = "Subclassed: DATE/TIME changed" Form1.Label3.Caption = "New Time : " & Time() Form1.Label4.Caption ="New Date : " & Format$(Date, "Long Date") 'message processed so return 0 WindowProc = 0 Case Else 'if subclassing has been activated, pass 'messages to the default message handler 'If it hasn't, then the default handler 'will take care of them by default. WindowProc = CallWindowProc(defWindowProc, _ hwnd, _ uMsg, _ wParam, _ lParam) Exit Function End Select Case Else 'this takes care of messages when the 'handle specified is not that of the form WindowProc = CallWindowProc(defWindowProc, _ hwnd, _ uMsg, _ wParam, _ lParam) End Select End Function |
Form Code |
Create a form containing four Labels (Label1-Label4), and three command buttons (Command1, Command2 and Command3). Keep the form name as "Form1", or be sure to change Form1 references throughout the app before running. And add the following code to the form: |
|
Option Explicit Private Sub Command1_Click() 'reset the titlebar caption during testing Me.Caption = "Subclassed: Change the Date/Time" End Sub Private Sub Command2_Click() 'show the control panel date/time properties Call Shell("rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,0",vbNormalFocus) End Sub Private Sub Command3_Click() Unload Me End Sub Private Sub Form_Load() Label1.Caption = "Start Time : " & Time() Label2.Caption = "Start Date : " & Format$(Date, "Long Date") 'subclass Call SubClass(Form1.hwnd) Command1.Value = True End Sub Private Sub Form_Unload(Cancel As Integer) If defWindowProc Then Call UnSubClass(Me.hwnd) End If End Sub |
Comments |
Save the program before trying to run, and use Start with Full Compile
to catch any coding errors. Open the date/time panel and change a setting, pressing OK or Apply.
Responding to the WM_TIMECHANGE event is not limited to changes made through the control panel. If an application happens to broadcast this message after making a system date/time change, this routine will detect that as well. To test the SendMessage method with this demo, add the following additional declarations to the BAS module: Public Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long Public Const HWND_TOPMOST = -1 ..and add new form to the project (Form1) and the following code to a command button on that form: Private Sub Command1_Click() Date = #2/6/1998# 'specify HWND_TOPMOST as the hWnd parameter 'to broadcast to all top-level windows Call SendMessage(HWND_TOPMOST, _ WM_TIMECHANGE, 0, ByVal 0) End SubAdd a Form1.Show command to the Form1 Load event, then run the demo again and press the Form1 command button. The system clock and the Form1 captions and labels will reflect the new change. And remember to set the date back before posting in a newsgroup or sending email !! |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |