Microsoft KB Archive/232625

= How To Create and Call a String Resource in a DLL with a Specific Locale ID =

Article ID: 232625

Article Last Modified on 6/29/2004

-

APPLIES TO


 * Microsoft Visual Basic 5.0 Professional Edition
 * Microsoft Visual Basic 6.0 Professional Edition
 * Microsoft Visual Basic 5.0 Enterprise Edition
 * Microsoft Visual Basic 6.0 Enterprise Edition

-



This article was previously published under Q232625



SUMMARY
This article demonstrates how to use Visual Basic to create a dynamic-link library (DLL) with an embedded localized string table in the resource file. It also demonstrates how to call a string resource in a DLL with a specific locale ID from a Visual Basic application.



MORE INFORMATION
Occasionally, problems occur using a multi-language resource file. To work around these problems, a localized string table can be created and attached 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 the application is distributed.

To build the following sample, you must create two DLLs with embedded resource files. 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.

Step-by-Step Example
 To create the DLLs with an embedded resource string table, follow the steps below. The first time through the steps, a DLL containing a Canadian English string table is created. The second time through, a US English string table is created and embedded in a second DLL:  Start a new Visual Basic ActiveX DLL project. Class1 is created by default. 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 then click OK. On the Tools menu, click the Resource Editor menu item. In the Visual Basic Resource Editor, click on the 'abc' icon to bring up the Edit String Tables dialog box. Double-click the language that is displayed, click the drop-down arrow, and then select English (Canadian) from the combobox. Double-click the text field below the language, and type in: Canadian English .</li> Make certain that the id number associated with this string is 101.</li> Dismiss the Edit String Table dialog box by clicking on the X in the upper-right-hand corner.</li> Click on the Save icon in the Visual Basic Resource Editor dialog box, and then save the file as res1009 in a folder named resourcedll. This automatically adds the RES file to the DLL project that you have created.</li> On the Project menu, select Project1 Properties. Change the Project Name field from Project1 to resdll1009. Save the resdll1009 project in the resourcedll folder.</li> Compile the resdll1009 project, saving the DLL to the resourcedll folder, and making certain that the Filename is resdll1009. The name of the DLL is important because it is loaded in the code using this file name.</li></ol> </li> Create a second DLL by repeating steps 1 - 12 with the following modifications: <ul> In step 5, set the language to English (US).</li> In step 6, type in the text: US English .</li> In step 9, save the RES file in the same folder but use the name res409.</li> In step 10, name the project resdll409 instead of resdll1009.</li> In step 11, save the resdll409 project to the resourcedll folder.</li> In step 12, compile the resdll409 project, saving the DLL to the resourcedll folder, and making certain the file name is resdll409.</li></ul>

</li> Perform the following steps to create the Standard EXE project: <ol> Start a new Visual Basic Standard EXE project. Form1 is created by default.</li> Add a label (Label1) to Form1.</li> <li> Add the following code to the General Declarations section of Form1: 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 </li> <li>You might need to modify the path to the Resource DLL in the preceding code. Run the application and the localized string should appear.</li> <li>Compile this Standard EXE project.</li></ol> </li> <li>Set the Regional Settings to English (Canada), which requires a reboot on some operating systems. Run the compiled application. This should display the Canadian English string in the label.</li> <li>Close down the application and change the regional settings to English (US). Run the program again and the US English string should be displayed.</li></ul>

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).

Make certain that 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 you need to create the RC file from scratch by using appropriate language settings and compile with the RC.exe resource compiler.

<div class="references_section">