|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Locale/Regionalization Routines SetLocaleInfo: Change System Long and Short Date Formats |
|
Posted: | Sunday August 8, 1999 |
Updated: | Monday December 26, 2011 |
Applies to: | VB5, VB6 |
Developed with: | VB6, Windows NT4 |
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 EnumDateFormats: Regional Locale Date Settings EnumTimeFormats: Regional Locale Time Settings GetLocaleInfo: Regional Locale Date Settings |
Prerequisites | ||||||||||||||||||||||||||||||
VB5 or VB6. | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Thus
far we've seen how to enumerate Locale information (date and time formats, separators etc), Calendar information (days and months, both full
and abbreviated), as well as retrieve date formats, the calendar type and assorted other national language
settings controlled through Windows' Regional Settings dialog.
A need may arise where an application requires that a specific long or short date format be implemented on the target machine. Applications for the public should never change a registry preference; it is always preferable to inform the user the current settings will cause difficulties and ask them to manually make the required change. But in-house applications targeting the corporate environment are an entirely different matter. In the corporate environment, computer management is the domain of the IT department, not the user. Given the mission-critical nature of business applications, the systems office is justified in dictating how a machine's long and short date are to be configured and as such any mechanism to test and revert to the correct system settings is warranted. Therefore, with this understanding, here is how to both retrieve and set the users short and long date formats to an application-defined string. This method also provides for changing the short date separator - for example if the separator is a slash - yyyy/mm/dd - and the IT department designates dates should use dashes - yyyy-mm-dd - setting the new short date will also change the default separator. In order demo only the most significant code required for this functionality the code allows the entering of and string as the new long or short date format. In practice, you'll want to add significant error checking to assure that only valid characters are entered. SetLocaleInfo only provides for changing of a subset of available locale settings, as outlined below. The two bolded items are those used in this demo. The following LCTYPE values are valid for this function:
|
||||||||||||||||||||||||||||||
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 thisCombo As ComboBox Public Const LOCALE_SLANGUAGE As Long = &H2 'localized name of language Public Const LOCALE_SSHORTDATE As Long = &H1F 'short date format string Public Const LOCALE_SLONGDATE As Long = &H20 'long date format string Public Const DATE_LONGDATE As Long = &H2 Public Const DATE_SHORTDATE As Long = &H1 Public Const HWND_BROADCAST As Long = &HFFFF& Public Const WM_SETTINGCHANGE As Long = &H1A Public Declare Function PostMessage Lib "user32" _ Alias "PostMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long Public Declare Function EnumDateFormats Lib "kernel32" _ Alias "EnumDateFormatsA" _ (ByVal lpDateFmtEnumProc As Long, _ ByVal Locale As Long, _ ByVal dwFlags As Long) As Long Public Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" _ (Destination As Any, _ Source As Any, _ ByVal Length As Long) Public Declare Function GetSystemDefaultLCID Lib "kernel32" () As Long Public Declare Function GetLocaleInfo Lib "kernel32" _ Alias "GetLocaleInfoA" _ (ByVal Locale As Long, _ ByVal LCType As Long, _ ByVal lpLCData As String, _ ByVal cchData As Long) As Long Public Declare Function SetLocaleInfo Lib "kernel32" _ Alias "SetLocaleInfoA" _ (ByVal Locale As Long, _ ByVal LCType As Long, _ ByVal lpLCData As String) As Long Public Function GetUserLocaleInfo(ByVal dwLocaleID As Long, _ ByVal dwLCType As Long) As String Dim sReturn As String Dim r As Long 'call the function passing the Locale type 'variable to retrieve the required size of 'the string buffer needed r = GetLocaleInfo(dwLocaleID, dwLCType, sReturn, Len(sReturn)) 'if successful.. If r Then 'pad the buffer with spaces sReturn = Space$(r) 'and call again passing the buffer r = GetLocaleInfo(dwLocaleID, dwLCType, sReturn, Len(sReturn)) 'if successful (r > 0) If r Then 'r holds the size of the string 'including the terminating null GetUserLocaleInfo = Left$(sReturn, r - 1) End If End If End Function Public Function EnumCalendarDateProc(lpDateFormatString As Long) As Long 'application-defined callback function for EnumDateFormats 'populates combo assigned to global var thisCombo thisCombo.AddItem StringFromPointer(lpDateFormatString) 'return 1 to continue enumeration EnumCalendarDateProc = 1 End Function Private Function StringFromPointer(lpString As Long) As String Dim pos As Long Dim buffer As String 'pad a string to hold the data buffer = Space$(128) 'copy the string pointed to by the return value CopyMemory ByVal buffer, lpString, ByVal Len(buffer) 'remove the trailing null and trim pos = InStr(buffer, Chr$(0)) If pos Then StringFromPointer = Left$(buffer, pos - 1) End If End Function |
||||||||||||||||||||||||||||||
Form Code | ||||||||||||||||||||||||||||||
Create a form containing two frames. Into Frame1 (Long Date
Info), place Combo1, Label1, Text1 and Command1. Into Frame2 place Combo2, Label2, Text2 and Command2.
Add two more command button (Command3 & 4) another text box (Text3), and the following code: |
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Option Explicit Private Sub Form_Load() Command1.Enabled = Combo1.ListIndex > -1 Command2.Enabled = Combo2.ListIndex > -1 Me.Move (Screen.Width - Me.Width) \ 2, (Screen.Height - Me.Height) \ 2 End Sub Private Sub Command1_Click() Dim LCID As Long Dim sNewFormat As String LCID = GetSystemDefaultLCID() sNewFormat = Combo1.Text If Len(sNewFormat) > 0 Then 'set the new long date format Call SetLocaleInfo(LCID, LOCALE_SLONGDATE, sNewFormat) 'send a system notification message that a change was made Call PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0&, ByVal 0&) 'update the textbox Text1.Text = GetUserLocaleInfo(LCID, LOCALE_SLONGDATE) 'assign the target combo box control and clear Set thisCombo = Form1.Combo1 thisCombo.Clear 'enumerate new long date formats Call EnumDateFormats(AddressOf EnumCalendarDateProc, LCID, DATE_LONGDATE) End If End Sub Private Sub Command2_Click() Dim LCID As Long Dim sNewFormat As String LCID = GetSystemDefaultLCID() sNewFormat = Combo2.Text If Len(sNewFormat) > 0 Then 'set the new long date format Call SetLocaleInfo(LCID, LOCALE_SSHORTDATE, sNewFormat) 'send a system notification message that a change was made Call PostMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0&, ByVal 0&) 'update the textbox and label Text2.Text = GetUserLocaleInfo(LCID, LOCALE_SSHORTDATE) 'assign the target combo box control Set thisCombo = Form1.Combo2 thisCombo.Clear 'enumerate new long date formats Call EnumDateFormats(AddressOf EnumCalendarDateProc, LCID, DATE_SHORTDATE) End If End Sub Private Sub Command3_Click() 'open the control panel Regional Date Settings Call Shell("rundll32.exe shell32.dll,Control_RunDLL intl.cpl,,4", vbNormalFocus) End Sub Private Sub Command4_Click() Dim LCID As Long LCID = GetSystemDefaultLCID() 'show localized name of language Text3.Text = GetUserLocaleInfo(LCID, LOCALE_SLANGUAGE) '------------------------- 'assign the target combo box control Set thisCombo = Form1.Combo1 'enumerate available long date formats Call EnumDateFormats(AddressOf EnumCalendarDateProc, LCID, DATE_LONGDATE) 'Show the user's Long date format string Text1.Text = GetUserLocaleInfo(LCID, LOCALE_SLONGDATE) '------------------------- 'assign the target combo box control Set thisCombo = Form1.Combo2 'enumerate available short date formats Call EnumDateFormats(AddressOf EnumCalendarDateProc, LCID, DATE_SHORTDATE) 'Show the user's Short date format string Text2.Text = GetUserLocaleInfo(LCID, LOCALE_SSHORTDATE) End Sub Private Sub Text1_Change() Label1.Caption = Format$(Date, Text1.Text) End Sub Private Sub Text2_Change() Label2.Caption = Format$(Date, Text2.Text) End Sub Private Sub Combo1_Click() Command1.Enabled = Combo1.ListIndex > -1 End Sub Private Sub Combo2_Click() Command2.Enabled = Combo2.ListIndex > -1 End Sub |
||||||||||||||||||||||||||||||
Comments | ||||||||||||||||||||||||||||||
Save the program and run. The values displayed should correspond to the date strings for your system. Select an alternate long or short date string, or create a new one and press Apply. Regional Settings are changed to reflect your new selection. Note that the control panel (on NT4 anyway) doesn't respond to the broadcast message posted - you'll need to close and reopen it to see the effected change. | ||||||||||||||||||||||||||||||
While the GetSystemDefaultLCID function retrieves the system default
locale identifier, this is often inappropriate or insufficient in a networked
environment or under an operating system where multiple locales have
been installed. For example, it is possible for a network admin rolling
out a standard image to have the user's default locale set to one
differing from the base OS installation, and thus the system default
locale. In this situation Windows' provides an alternate API you can use to obtain the LCID for the current user ... GetUserDefaultLCID. Defined identically to GetSystemDefaultLCID, GetUserDefaultLCID function retrieves the user default–locale identifier and is therefore the most appropriate API to use when it is the user's locale you are interested in, rather than that of the system. |
||||||||||||||||||||||||||||||
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |