在VB6中显示Unicode文本(希伯来语等)的最佳选择是什么?

What's the best option to display Unicode text (hebrew, etc.) in VB6

我有一些客户想要在希伯来语中使用我们的语音治疗软件。

程序在VB6中。 我知道的最佳选择是:

  • 使用MS Office中的Forms 2.0控件,但不能分发它们。
  • http://www.hexagora.com/en_dw_unictrl.asp 899美元
  • http://www.iconico.com/UniToolbox/ $ 499
  • 还有其他选择吗?


    我发现本教程非常有用。是的,它在某种程度上是另一个Unicode Control Suite的广告,但是它具有许多有关如何自己做以及涉及哪些问题的信息。

    编辑

    我知道我在书签中拥有更多的存储方式。

    首先,Chilkat(另一个组件供应商)写了一篇文章,介绍如何使用字体的字符集(假设它是unicode字体)来设置不同的字体类型(您必须手动更改.frm,因为字符集未公开gui)。然后,您所要做的就是从AnsiToUTF8转换为支持不同的语言(Chilkat的控件就是这样做的)。

    其次,这里有Vesa Piittinen的免费VB6控件(包括知识共享),包括VB6控件。它们包括文本框,标签,菜单,列表,对话框,命令按钮,标题(窗体的标题))。我没有和他们玩太多,但是基本上他正在做所有的onPaint,而且很高兴的是,这些都是在VB中完成的,您可以看一下源代码。


    大概您的用户没有选择希伯来语作为系统默认代码页,否则您可以只使用本机VB6控件(请记住,希伯来语是从右到左!)。

    不要使用Forms 2-它将使您的VB6程序崩溃。 Microsoft知识库文章:"与Visual Basic和其他开发人员产品一起使用时,FM20.DLL已知有很多问题。在任何Visual Studio产品中均不建议也不支持使用它。"

    我没有其他人的亲身经历,但是您的#3选项UniToolbox已经存在很多年了,Google在新闻组中对此发表了一些积极的讨论(编辑-例如VB6国际化专家Michael Kaplan在2004年的帖子中推荐了它)和2005年的博客文章)。

    一种怪异的选择是将API调用与本机VB6控件一起使用-Michael Kaplan着书中有关VB6的国际化的出色著作中的一些指针,以及他网站上的一些示例代码。但这将需要大量工作。无论如何都要购买这本书,因为它是VB6中有关国际问题的金矿。例如,示例章节说明了希伯来语的问题。二手,因为它已经绝版。


    这是有关使用资源(.RES)文件以Microsoft Visual Basic形式显示Unicode字符的一些注释:

    当我在创建资源(.RES)文件时将俄语或日语字符粘贴到Microsoft Visual Basic 6资源编辑器时,这些字符在带有俄语或日语的计算机上显示的MSVB6资源编辑器和MSVB6表单中都将显示为问号(?)。日语语言环境分别使用我通过MSVB6从RES文件构建的资源DLL。

    但是,如果我通过将字符粘贴到Resource Hacker http://www.angusj.com/resourcehacker中将字符添加到资源文件中,则这些字符仍将在MSVB6资源编辑器中显示为问号,但在具有以下功能的计算机上可以正确显示通过MSVB6构建资源DLL之后的适当语言环境。

    可以为多种语言中的每一种制作资源DLL,并使用Microsoft的GetUserDefaultLCID或GetUserDefaultLocaleName来决定加载哪个。


    该链接的字符集表

    enter image description here

    • DBCS-双字节字符集

    实际上,DBCS不是Windows使用的正确术语。实际上是MBCS,其中字符可以是1或2个字节。为了说明这一点,请考虑以下代码,该代码将使用中英文字符的Unicode字符串,转换为MBCS中文的字节数组,将字节数组转储到立即窗口中,最后将其转换回Unicode字符串,以在Unicode识别文本框。使用中文(PRC)LCID = 2052转换时的字节数组包含英语字符的单字节和Unicode字符的双字节。这证明它是MBCS而不是DBCS:


    这就是您所需要的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    Option Explicit
    '
    Private Type GETTEXTEX
        cb As Long
        flags As Long
        codepage As Long
        lpDefaultChar As Long
        lpUsedDefChar As Long
    End Type
    '
    Private Type GETTEXTLENGTHEX
        flags As Long
        codepage As Long
    End Type
    '
    Private Type SETTEXTEX
        flags As Long
        codepage As Long
    End Type
    '
    Private Declare Function DefWindowProcW Lib"user32" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Sub PutMem4 Lib"msvbvm60" (Destination As Any, Value As Any)
    Private Declare Function SysAllocStringLen Lib"oleaut32" (ByVal OleStr As Long, ByVal bLen As Long) As Long
    Private Declare Function OpenClipboard Lib"user32.dll" (ByVal hWnd As Long) As Long
    Private Declare Function EmptyClipboard Lib"user32.dll" () As Long
    Private Declare Function CloseClipboard Lib"user32.dll" () As Long
    Private Declare Function IsClipboardFormatAvailable Lib"user32.dll" (ByVal wFormat As Long) As Long
    Private Declare Function GetClipboardData Lib"user32.dll" (ByVal wFormat As Long) As Long
    Private Declare Function SetClipboardData Lib"user32.dll" (ByVal wFormat As Long, ByVal hMem As Long) As Long
    Private Declare Function GlobalAlloc Lib"kernel32.dll" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
    Private Declare Function GlobalLock Lib"kernel32.dll" (ByVal hMem As Long) As Long
    Private Declare Function GlobalUnlock Lib"kernel32.dll" (ByVal hMem As Long) As Long
    Private Declare Function GlobalSize Lib"kernel32" (ByVal hMem As Long) As Long
    Private Declare Function lstrcpy Lib"kernel32.dll" Alias"lstrcpyW" (ByVal lpString1 As Long, ByVal lpString2 As Long) As Long
    Private Declare Function SendMessage Lib"user32.dll" Alias"SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
    Private Declare Function SendMessageWLng Lib"user32" Alias"SendMessageW" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    '
    ' The following is from MSDN help:
    '
    ' UNICODE: International Standards Organization (ISO) character standard.
    ' Unicode uses a 16-bit (2-byte) coding scheme that allows for 65,536 distinct character spaces.
    ' Unicode includes representations for punctuation marks, mathematical symbols, and dingbats,
    ' with substantial room for future expansion.
    '
    ' vbUnicode constant:     Converts the string toUnicode using the default code page of the system.
    ' vbFromUnicode constant: Converts the string from Unicode to the default code page of the system.
    '
    ' LCID: The LocaleID, if different than the system LocaleID. (The system LocaleID is the default.)
    '

    Public Property Let UniCaption(ctrl As Object, sUniCaption As String)
        Const WM_SETTEXT As Long = &HC
        ' USAGE: UniCaption(SomeControl) = s
        '
        ' This is known to work on Form, MDIForm, Checkbox, CommandButton, Frame, & OptionButton.
        ' Other controls are not known.
        '
        ' As a tip, build your Unicode caption using ChrW.
        ' Also note the careful way we pass the string to the unicode API call to circumvent VB6's auto-ASCII-conversion.
        DefWindowProcW ctrl.hWnd, WM_SETTEXT, 0&, ByVal StrPtr(sUniCaption)
    End Property

    Public Property Get UniCaption(ctrl As Object) As String
        Const WM_GETTEXT As Long = &HD
        Const WM_GETTEXTLENGTH As Long = &HE
        ' USAGE: s = UniCaption(SomeControl)
        '
        ' This is known to work on Form, MDIForm, Checkbox, CommandButton, Frame, & OptionButton.
        ' Other controls are not known.
        Dim lLen As Long
        Dim lPtr As Long
        '
        lLen = DefWindowProcW(ctrl.hWnd, WM_GETTEXTLENGTH, 0&, ByVal 0&) ' Get length of caption.
        If lLen Then ' Must have length.
            lPtr = SysAllocStringLen(0&, lLen) ' Create a BSTR of that length.
            PutMem4 ByVal VarPtr(UniCaption), ByVal lPtr ' Make the property return the BSTR.
            DefWindowProcW ctrl.hWnd, WM_GETTEXT, lLen + 1&, ByVal lPtr ' Call the default Unicode window procedure to fill the BSTR.
        End If
    End Property

    Public Property Let UniClipboard(sUniText As String)
        ' Puts a VB string in the clipboard without converting it to ASCII.
        Dim iStrPtr As Long
        Dim iLen As Long
        Dim iLock As Long
        Const GMEM_MOVEABLE As Long = &H2
        Const GMEM_ZEROINIT As Long = &H40
        Const CF_UNICODETEXT As Long = &HD
        '
        OpenClipboard 0&
        EmptyClipboard
        iLen = LenB(sUniText) + 2&
        iStrPtr = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, iLen)
        iLock = GlobalLock(iStrPtr)
        lstrcpy iLock, StrPtr(sUniText)
        GlobalUnlock iStrPtr
        SetClipboardData CF_UNICODETEXT, iStrPtr
        CloseClipboard
    End Property

    Public Property Get UniClipboard() As String
        ' Gets a UNICODE string from the clipboard and puts it in a standard VB string (which is UNICODE).
        Dim iStrPtr As Long
        Dim iLen As Long
        Dim iLock As Long
        Dim sUniText As String
        Const CF_UNICODETEXT As Long = 13&
        '
        OpenClipboard 0&
        If IsClipboardFormatAvailable(CF_UNICODETEXT) Then
            iStrPtr = GetClipboardData(CF_UNICODETEXT)
            If iStrPtr Then
                iLock = GlobalLock(iStrPtr)
                iLen = GlobalSize(iStrPtr)
                sUniText = String$(iLen \\ 2& - 1&, vbNullChar)
                lstrcpy StrPtr(sUniText), iLock
                GlobalUnlock iStrPtr
            End If
            UniClipboard = sUniText
        End If
        CloseClipboard
    End Property

    Public Sub SetupRichTextboxForUnicode(rtb As RichTextBox)
        ' Call this so that the rtb doesn't try to do any RTF interpretation.  We will just be using it for Unicode display.
        ' Once this is called, the following two procedures will work with the rtb.
        Const TM_PLAINTEXT As Long = 1&
        Const EM_SETTEXTMODE As Long = &H459
        SendMessage rtb.hWnd, EM_SETTEXTMODE, TM_PLAINTEXT, 0& ' Set the control to use"plain text" mode so RTF isn't interpreted.
    End Sub

    Public Property Let RichTextboxUniText(rtb As RichTextBox, sUniText As String)
        ' Usage: Just assign any VB6 string to the rtb.
        '        If the string contains Unicode (which VB6 strings are capable of), it will be correctly handled.
        Dim stUnicode As SETTEXTEX
        Const EM_SETTEXTEX As Long = &H461
        Const RTBC_DEFAULT As Long = 0&
        Const CP_UNICODE As Long = 1200&
        '
        stUnicode.flags = RTBC_DEFAULT ' This could be otherwise.
        stUnicode.codepage = CP_UNICODE
        SendMessageWLng rtb.hWnd, EM_SETTEXTEX, VarPtr(stUnicode), StrPtr(sUniText)
    End Property

    Public Property Get RichTextboxUniText(rtb As RichTextBox) As String
        Dim uGTL As GETTEXTLENGTHEX
        Dim uGT As GETTEXTEX
        Dim iChars As Long
        Const EM_GETTEXTEX As Long = &H45E
        Const EM_GETTEXTLENGTHEX As Long = &H45F
        Const CP_UNICODE As Long = 1200&
        Const GTL_USECRLF As Long = 1&
        Const GTL_PRECISE As Long = 2&
        Const GTL_NUMCHARS As Long = 8&
        Const GT_USECRLF As Long = 1&
        '
        uGTL.flags = GTL_USECRLF Or GTL_PRECISE Or GTL_NUMCHARS
        uGTL.codepage = CP_UNICODE
        iChars = SendMessageWLng(rtb.hWnd, EM_GETTEXTLENGTHEX, VarPtr(uGTL), 0&)
        '
        uGT.cb = (iChars + 1) * 2
        uGT.flags = GT_USECRLF
        uGT.codepage = CP_UNICODE
        RichTextboxUniText = String$(iChars, 0&)
        SendMessageWLng rtb.hWnd, EM_GETTEXTEX, VarPtr(uGT), StrPtr(RichTextboxUniText)
    End Property

    Public Sub SaveStringToUnicodeFile(sData As String, sFileSpec As String)
        ' These are typically .TXT files.  They can be read with notepad.
        Dim iFle As Long
        '
        iFle = FreeFile
        Open sFileSpec For Binary As iFle
        Put iFle, , &HFEFF ' This is the Unicode header to a text file.  First byte = FF, second byte = FE.
        Put iFle, , UnicodeByteArrayFromString(sData)
        Close iFle
    End Sub

    Public Function LoadStringFromUnicodeFile(sFileSpec As String) As String
        ' These are typically .TXT files.  They can be read with notepad.
        Dim iFle As Long
        Dim bb() As Byte
        Dim i As Integer
        '
        iFle = FreeFile
        Open sFileSpec For Binary As iFle
        Get iFle, , i
        If i <> &HFEFF Then ' Unicode file header.  First byte = FF, second byte = FE.
            Close iFle
            Exit Function ' It's not a valid Unicode file.
        End If
        ReDim bb(1 To LOF(iFle) - 2&)
        Get iFle, , bb
        Close iFle
        LoadStringFromUnicodeFile = bb ' This directly copies the byte array to the Unicode string (no conversion).
        ' Note: If you try to directly read the file as a string, VB6 will attempt to convert the string from ASCII to Unicode.
    End Function

    Public Function AsciiByteArrayFromString(s As String) As Byte()
       ' This converts the"s" string to an ASCII string before placing in the byte array.
       AsciiByteArrayFromString = StrConv(s, vbFromUnicode)
    End Function

    Public Function StringFromAsciiByteArray(bb() As Byte) As String
        ' This assumes that the"bb" array uses only one byte per character and expands it to UNICODE before placing in string.
        StringFromAsciiByteArray = StrConv(bb, vbUnicode)
    End Function

    Public Function UnicodeByteArrayFromString(s As String) As Byte()
        ' This directly copies the Unicode string into the byte array, using two bytes per character (i.e., Unicode).
        UnicodeByteArrayFromString = s
    End Function

    Public Function StringFromUnicodeByteArray(bb() As Byte) As String
        ' This directly copies the byte array into the Unicode string, using two bytes per character.
        '
        ' Interestingly, you can assign an odd number of bytes to a string.
        ' The Len(s) function will not count the last (odd) byte, but the LenB(s) function will correctly report it.
        ' However, it is advisable to keep the byte array an even number of bytes.
        StringFromUnicodeByteArray = bb
    End Function

    根据KB224305(" INFO:FM20.DLL的使用和重新分发"),您可以安装免费的" Microsoft ActiveX控件板",后者又将安装Forms 2.0库。

    也许这是您的选择。