Reputation: 805
I created a String Resource .RES file in Visual Studio 2019 with various string tables for multiple languages, then I compiled the .RES into a VB6 DLL (no code, the VB6 project is just a compiled VB6 DLL). Here is the no-code VB6 project that creates the DLL:
I then read the strings from this DLL into a VB6 program, and output to a Unicode-aware label control.
The strings read/output fine from English and Arabic, but for Hebrew, it just shows the same character.
Option Explicit
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 LoadStringW Lib "user32" (ByVal hInstance As Long, ByVal wID As Long, ByVal lpBuffer As String, ByVal nBufferMax As Long) As Long ' Works Arabic
Private Declare Function SetThreadUILanguage Lib "kernel32" (ByVal dwLCID As Long) As Long
Private Declare Function SetThreadLocale Lib "kernel32" (ByVal dwLCID As Long) As Long
Private Sub Form_Load()
Dim hInst As Long, lResult As Long
Dim resstring As String
Dim icc As Long
Const STRLENGTH As Long = 1000
Const HEBREW As Long = 1037
Const ARABIC As Long = 3073
Const ENGLISH As Long = 1033
icc = ENGLISH ' convenience, set it once here
SetThreadUILanguage icc
SetThreadLocale icc
hInst = LoadLibrary("c:\temp\resstr.dll")
If hInst Then
resstring = String(STRLENGTH, Chr(0))
If icc = ENGLISH Then
lResult = LoadString(hInst, 101, resstring, STRLENGTH)
Label1.Caption = Left$(resstring, lResult)
Else
lResult = LoadStringW(hInst, 101, resstring, STRLENGTH)
Label1.Caption = StrConv(Left(resstring, lResult * 2), vbFromUnicode, icc)
End If
lResult = FreeLibrary(hInst)
End If
End Sub
As you can see, the Arabic output is fine (and so is the English, just not screen captured). BUT...the Hebrew prints out the same character?!
Upvotes: 4
Views: 374
Reputation: 805
FIX: In Control Panel/Region/Administrative tab, I had to change the "Current language for non-Unicode programs" to 'Hebrew' or 'Arabic' to get it to display correctly. @GSerg also added helpful tips of properly calling a W function.
Upvotes: 1
Reputation: 78190
You cannot Declare
an argument As String
to the *W
family of functions.
VB6 will automatically convert a String
to the current system codepage for non-Unicode programs when calling into a Declare
d function, and convert back to Unicode when the call returns. This mechanism is designed to interact with the *A
family of functions that deal with ANSI.
When calling a *W
function in that way, not only the Unicode data will be destroyed even before you get a chance to execute your StrConv(vbFromUnicode)
(which you should almost never do, and here it will only destroy the data even further), but you also have a buffer overflow where you promise to the function that you have provided 1000 characters of space, whereas you only provide 1000 bytes, which is half as much.
In order to call a *W
function, you must declare the string buffer As Long
and pass StrPtr()
of the string variable.
You also don't need to fall back to LoadStringA
, as it is nothing more than a wrapper around LoadStringW
.
Your declaration for SetThreadUILanguage
is also wrong (LANGID
is an Integer
, as opposed to LCID
which is a Long
).
Option Explicit
Private Declare Function LoadStringW Lib "user32" (ByVal hInstance As Long, ByVal wID As Long, ByVal lpBuffer As Long, ByVal nBufferMax As Long) As Long
Private Declare Function SetThreadUILanguage Lib "kernel32" (ByVal LangId As Integer) As Integer
Private Declare Function SetThreadLocale Lib "kernel32" (ByVal dwLCID As Long) As Long
Private Sub Form_Load()
Dim hInst As Long, lResult As Long
Dim resstring As String
Dim icc As Long
Const STRLENGTH As Long = 1000
Const HEBREW As Long = 1037
Const ARABIC As Long = 3073
Const ENGLISH As Long = 1033
icc = ENGLISH ' convenience, set it once here
SetThreadUILanguage icc
SetThreadLocale icc
hInst = LoadLibrary("c:\temp\resstr.dll")
If hInst Then
resstring = String(STRLENGTH, vbNullChar)
lResult = LoadStringW(hInst, 101, StrPtr(resstring), STRLENGTH)
Label1.Caption = Left$(resstring, lResult)
lResult = FreeLibrary(hInst)
End If
End Sub
Upvotes: 3