|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
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. |
![]() |