Re: VB6 ANSI to Unicode conversion wrong with fixed-length strings in structures



You may want to check these articles...

http://support.microsoft.com/default.aspx?scid=kb;en-us;205277

http://support.microsoft.com/default.aspx?scid=kb;en-us;199824

Especially read the part about StrPtr() in the last article.

VB auto converts between ANSI/Unicode when you use ByVal keyword, but not
when a string is passed ByRef. In ByRef case, the string is based as is, in
Unicode format. VB UI is ANSI only, so if you print text that is not in the
current code page, you will see question marks. One way to show Unicode
chars in VB6 for testing only is by using "Microsoft Forms 2.0 Object
Library" in Project|Components. This will add some Unicode controls to your
project, but you can't redistribute this component, because it requires and
comes with MS Office. If you want UI Unicode support, you have to make your
own, require the user to get MS Office, or get a third party control...



"MarkJackson" <mark@xxxxxxxxxx> wrote in message
news:1126008342.898761.221930@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Hi
>
> Briefly:
> I have a Fortran DLL that returns a structure containing fixed-length
> strings to a VB6 program. Fine for English characters, but not for
> returning Chinese characters (using Chinese code page on the PC). In my
> debugger the strings are correct in the DLL, but in the VB there are
> garbage characters at the end. I can only think that VB's implicit ANSI
> to Unicode conversion has messed up. Can anyone help with this?
>
> Details, with code:
> I'm calling a DLL from VB6 with a Declare statement, passing a
> structure containing fixed-length strings of length 20 characters.
> Behind the scenes VB creates a copy of the structure with ANSI strings
> of 20 bytes. When the DLL returns, VB converts the strings from ANSI to
> Unicode and copies the data back to the original structure.
>
> If the DLL writes one Chinese character at the start of a 20 byte
> string, that takes 2 bytes (in ANSI encoding). It pads with spaces,
> making 19 characters in the 20 bytes. VB implicitly converts the
> strings from ANSI to Unicode when the DLL returns. Those 19 characters
> convert fine, but the 20th character in the VB string is garbage. VB
> seems to just interpret the next two bytes in the structure (past the
> end of the string!) as a Unicode character. And I don't mean it
> converts them from ANSI! If the next two bytes are both hex 0x20, you
> don't get a space, you get the Unicode character 0x2020.
>
> I'm not going to explain why we're using Fortran DLLs, but there are
> reasons! I think the same would happen with a C DLL but don't have time
> to test it now. (I'm using Compaq Visual Fortran 6 by the way)
>
> VB source code, in a form with a button:
>>>>
>
> Private Type testStruct
> sTestOne As String * 20
> bytArray(0 To 20) As Byte
> End Type
>
> Private Declare Function TestDllFunction Lib "test32.dll" (ByRef
> nTestNum As Integer, ByRef testStruct As testStruct) As Integer
>
> Private Sub cmdTest_Click()
> Dim i As Integer
> Dim testRec As testStruct
> Dim nNumChars As Integer
>
> 'Put some marker bytes past the string to help diagnose problem
> For i = 0 To 20
> testRec.bytArray(i) = 32 + i
> Next i
>
> nNumChars = 1
> i = TestDllFunction(nNumChars, testRec)
>
> Debug.Assert False
> 'Check testRec.sTestOne here - one garbage character at the end
> 'for each Chinese character returned
> End Sub
>
> <<<<
>
> DLL source code. Fortran, but hopefully readable? ACHAR is like Chr$,
> and I've hardcoded the ANSI encodings for the Chinese characters from 1
> to 10
>>>>>
>
> INTEGER*2 FUNCTION TestDllFunction
> + (nNumChars, testRec )
> IMPLICIT NONE
> !DEC$ ATTRIBUTES DLLEXPORT::TestDllFunction !
> This exports the name from the DLL
> !DEC$ ATTRIBUTES ALIAS : "TestDllFunction" :: TestDllFunction !
> This makes the name accessible to VB6
> C ---
> INTEGER*2 nNumChars
> STRUCTURE /testStruct/
> CHARACTER*20 sTestOne
> INTEGER*1 bytArray(0:20)
> END STRUCTURE
> RECORD /testStruct/ testRec
> INTEGER*2 i
> C ---
> !The Chinese characters for one to ten,
> !when interpreted on simplified Chinese code page (936)
> testRec%sTestOne(1:2) = ACHAR('D2'X) // ACHAR('BB'X)
> testRec%sTestOne(3:4) = ACHAR('B6'X) // ACHAR('FE'X)
> testRec%sTestOne(5:6) = ACHAR('C8'X) // ACHAR('FD'X)
> testRec%sTestOne(7:8) = ACHAR('CB'X) // ACHAR('C4'X)
> testRec%sTestOne(9:10) = ACHAR('CE'X) // ACHAR('E5'X)
> testRec%sTestOne(11:12) = ACHAR('C1'X) // ACHAR('F9'X)
> testRec%sTestOne(13:14) = ACHAR('C6'X) // ACHAR('DF'X)
> testRec%sTestOne(15:16) = ACHAR('B0'X) // ACHAR('CB'X)
> testRec%sTestOne(17:18) = ACHAR('BE'X) // ACHAR('C5'X)
> testRec%sTestOne(19:20) = ACHAR('CA'X) // ACHAR('AE'X)
>
> !Pad any leftover with spaces
> DO i=(nNumChars*2)+1, 20
> testRec%sTestOne(i:i) = ACHAR(32)
> END DO
> C ---
> TestDllFunction=1
> RETURN
> END
>
> <<<<
>


.