HOWTO: Create and Call a String Resource in a DLL with a Specific Locale ID

ID: Q232625


The information in this article applies to:
  • Microsoft Visual Basic Professional and Enterprise Editions for Windows, versions 5.0, 6.0


SUMMARY

Occasionally, problems occur using a multi-language resource file. For example, please see the following article in the Microsoft Knowledge Base:

Q165188 INFO: Resource Language Decided by ResourceLocale Key on Win95
To work around these problems, create a localized string table and attach it to a DLL as a resource. This DLL can be loaded and strings displayed based on the current locale set in the Regional Settings. This technique requires that a separate resource DLL be created for each locale where your application is distributed.


MORE INFORMATION

To build the sample below you must to create two DLLs with an embedded resource file. You also need to create a standard EXE project that displays the strings stored as resources in the DLLs. The DLL file names contain the locale identifier associated with the regional setting selected by the user.

  • To create the DLLs with an embedded resource string table, do the following. The first time through the steps a DLL containing a Canadian English String table is created. The second time a US English string table is created and embedded in a DLL:


    1. Start a new Visual Basic ActiveX DLL project. Class1 is created by default.


    2. On the Add_Ins menu, select Add-In Manager. In the Add-In Manager dialog box, double-click the Visual Basic 6.0 Resource Editor. Confirm that the LoadBehavior column on the right-hand side of the window specifies Loaded, and click OK.


    3. From the Tools menu, click the Resource Editor menu item.


    4. In the Visual Basic Resource Editor, click on the 'abc' icon to bring up the Edit String Tables dialog box.


    5. Double-click the language displayed, click the drop-down arrow, and select English (Canadian) from the drop-down combobox.


    6. Double-click the text field below the language and enter the following: Canadian English.


    7. Make certain that the id number associated with this string is 101.


    8. Dismiss the Edit String Table dialog box by clicking on the X in the upper-right-hand corner.


    9. Click on the Save icon in the Visual Basic Resource Editor dialog box and save the file in a folder named resourcedll as res1009. This automatically adds the RES file to the DLL project that you have created.


    10. On the Project menu, select Project1 Properties. Change the Project Name field from Project1 to resdll1009.


    11. Save the resdll1009 project in the resourcedll folder.


    12. Compile the resdll1009 project, saving the DLL to the resourcedll folder, making certain the Filename is resdll1009. The name of the DLL is important because it will be loaded in the code using this file name.


  • Create a second DLL by repeating steps 1 - 14 with the following modifications:

    In step 5, set the language to English (US).
    In step 6, enter the text: US English
    In step 9, save the RES file in the same folder but use the name res409.
    In step 10, name of the project resdll409 instead of resdll1009.
    In step 11, save the resdll409 project to the resourcedll folder.
    In step 12, compile the resdll409 project, saving the DLL to the resourcedll folder, and making certain the file name is resdll409.


  • Perform the following steps to create the Standard EXE project:


    1. Start a new Visual Basic Standard EXE project. Form1 is created by default.


    2. Add a label (Label1) to Form1.


    3. Add the following code to the General Declarations section of Form1:


    4. 
      Option Explicit
      
      Private Declare Function GetThreadLocale Lib "kernel32" () As Long
      Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" _
         (ByVal lpLibFileName As String) As Long
      Private Declare Function LoadString Lib "user32" Alias "LoadStringA" _
         (ByVal hInstance As Long, ByVal wID As Long, ByVal lpBuffer As String, _
          ByVal nBufferMax As Long) As Long
      Private 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
      
      Private Const LOCALE_IDEFAULTANSICODEPAGE = &H1004&
      Private Const LOCALE_SENGCOUNTRY = &H1002
      Private Const LOCALE_SNATIVECTRYNAME = &H8
      Private Const LOCALE_SCOUNTRY = &H6
      
      Function GetCharSet(sCdpg As String) As Integer
         Select Case sCdpg
            Case "932" ' Japanese
               GetCharSet = 128
            Case "936" ' Simplified Chinese
               GetCharSet = 134
            Case "949" ' Korean
               GetCharSet = 129
            Case "950" ' Traditional Chinese
               GetCharSet = 136
            Case "1250" ' Eastern Europe
               GetCharSet = 238
            Case "1251" ' Russian
               GetCharSet = 204
            Case "1252" ' Western European Languages
               GetCharSet = 0
            Case "1253" ' Greek
               GetCharSet = 161
            Case "1254" ' Turkish
               GetCharSet = 162
            Case "1255" ' Hebrew
               GetCharSet = 177
            Case "1256" ' Arabic
               GetCharSet = 178
            Case "1257" ' Baltic
               GetCharSet = 186
            Case Else
               GetCharSet = 0
         End Select
      End Function
      Function StripNullTerminator(sCP As String)
         Dim posNull As Long
         posNull = InStr(sCP, Chr$(0))
         StripNullTerminator = Left$(sCP, posNull - 1)
      End Function
      Private Sub Form_Load()
         Dim hInst As Long, lResult As Long, x As Long
         Dim LCID As Long, sLcid As String
         Dim resString As String * 255
         Dim sCodePage As String
      
         sCodePage = String$(16, " ")
         Label1.AutoSize = True
         Label1.Caption = ""
      
         LCID = GetThreadLocale() 'Get Current locale
         sLcid = Hex$(Trim$(CStr(LCID))) 'Convert to Hex
         ' Display decimal value of the LCID (Hex in Parentheses)
         Form1.Caption = "LCID " & LCID & " (" & sLcid & ")"
         x = GetLocaleInfo(LCID, LOCALE_IDEFAULTANSICODEPAGE, _
             sCodePage, Len(sCodePage))  'Get code page
         sCodePage = StripNullTerminator(sCodePage)
         ' Load dll with string table resource.
         ' Might need to change path for the resdll.
         hInst = LoadLibrary("resdll" & sLcid & ".dll")
      
         ' Get string with ID 101.
         lResult = LoadString(hInst, 101, resString, 255)
         With Label1.Font
            .Name = "Lucida Sans Unicode"
            .Size = 14
            .Charset = GetCharSet(sCodePage)  'Convert code page to charset
         End With
         ' Display the localized string.
         Label1.Caption = resString
      End Sub 
    5. You might need to modify the path to the Resource DLL in the code above. Run the application and the localized string should appear.


    6. Compile this Standard EXE project.


  • Set the Regional Settings to English (Canada), which will require a reboot on some operating systems. Run the compiled application. This should display the Canadian English string in the label.


  • Close down the application and change the regional settings to English (US). Run the program again and the US English string should be displayed.


This sample works as a compiled EXE. It does not detect a change to the Locale ID if it is modified while the application is running or if run in the IDE. To update to the current Locale ID, create an ActiveX EXE that can be created in a new, separate thread, and retrieve the Locale ID (LCID).

The following Microsoft Knowledge Base article provides details:
Q217751 HOWTO: Get the Current User Locale ID in a VB EXE Without Restarting
Make certain your system has the appropriate code page and fonts. If you are going between code pages you need to use the Resource Editor Add-In that comes with Visual Basic 6.0 on the localized platform or create the RC file from scratch using appropriate language settings and compile with the RC.exe resource compiler.


REFERENCES

For additional information about using resource files for localization, please click the article number below to view the article in the Microsoft Knowledge Base:

Q165188 INFO: Resource Language Decided by ResourceLocale Key on Win95
Q217751 HOWTO: Get the Current User Locale ID in a VB EXE Without Restarting

Additional query words: International multilanguage

Keywords : kbsample kbDLL kbIntl kbResourceEd kbString kbVBp kbVBp500 kbVBp600 kbLocalization kbGrpVB kbDSupport
Version : WINDOWS:5.0,6.0
Platform : WINDOWS
Issue type : kbhowto


Last Reviewed: November 10, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.