To register for an Internet.com membership to receive newsletters and white papers, use the Register button ABOVE.
To participate in the message forums BELOW, click here
VBForums  

VB Wire News
Article :: Building Dynamic Systems with Expressions in .NET
How Is XML Like An Interface?
Understanding Covariance and Contravariance
Print VS 2010 Keyboard Shortcut References in Letter (8.5x11in) and A4 (210×297mm) Sizes
Updated Productivity Power Tools



Go Back   VBForums > Visual Basic > Visual Basic FAQs

Reply Post New Thread
 
Thread Tools Display Modes
Old Oct 14th, 2005, 11:51 PM   #1
Merri
VB6, XHTML & CSS hobbyist
 
Merri's Avatar
 
Join Date: Oct 02
Location: Finland
Posts: 6,330
Merri is a splendid one to behold (700+)Merri is a splendid one to behold (700+)Merri is a splendid one to behold (700+)Merri is a splendid one to behold (700+)Merri is a splendid one to behold (700+)Merri is a splendid one to behold (700+)Merri is a splendid one to behold (700+)Merri is a splendid one to behold (700+)
Classic VB - Does Visual Basic 6 support Unicode?

Yes and no. For yes, VB strings can hold 16-bit characters and is thus Unicode compatible. The problems come from several directions:
  • Strings passed to API are converted to ANSI and vice versa
  • Reading a file to a string is done by automatically converting ANSI to Unicode
  • The same applies when saving: string is converted to ANSI
  • Visual Basic controls are not Unicode aware
Luckily we have byte arrays to help us with the reading and writing business: they are easy to convert to strings and string contents can be copied to byte arrays easily with native VB code. Thus when working with Unicode, a byte array is your best bet.


Where are the controls?

The worst news is that VB6 controls use ANSI. The VB propertybags can't hold Unicode data and VB runtime also passes the data to the controls after ANSI conversion. Thus none of the default controls can be used for Unicode. The only free choice left is to code the controls by yourself or to seek for controls done by others on the internet. The easy solution costs money: people are selling Unicode aware controls and there is no free version available for many. Personally, I've made a UniLabel and a UniCommand and both are available for free (link).


Switching codepages

This code is still a work in progress: it is a simple module that allows to switch between codepages. This includes UTF-8 conversions, which might be handy. The functions take in and return a byte array. This far I haven't found an error with the current code. Use GetACP to find out the default codepage the system has in use (this codepage is used when a file is loaded by VB into a string).

VB Code:
  1. Option Explicit
  2. Public Enum KnownCodePage
  3.     CP_UNKNOWN = -1
  4.     CP_ACP = 0
  5.     CP_OEMCP = 1
  6.     CP_MACCP = 2
  7.     CP_THREAD_ACP = 3
  8.     CP_SYMBOL = 42
  9. '   ARABIC
  10.     CP_AWIN = 101   ' Bidi Windows codepage
  11.     CP_709 = 102    ' MS-DOS Arabic Support CP 709
  12.     CP_720 = 103    ' MS-DOS Arabic Support CP 720
  13.     CP_A708 = 104   ' ASMO 708
  14.     CP_A449 = 105   ' ASMO 449+
  15.     CP_TARB = 106   ' MS Transparent Arabic
  16.     CP_NAE = 107    ' Nafitha Enhanced Arabic Char Set
  17.     CP_V4 = 108     ' Nafitha v 4.0
  18.     CP_MA2 = 109    ' Mussaed Al Arabi (MA/2) CP 786
  19.     CP_I864 = 110   ' IBM Arabic Supplement CP 864
  20.     CP_A437 = 111   ' Ansi 437 codepage
  21.     CP_AMAC = 112   ' Macintosh Code Page
  22. '   HEBREW
  23.     CP_HWIN = 201   ' Bidi Windows codepage
  24.     CP_862I = 202   ' IBM Hebrew Supplement CP 862
  25.     CP_7BIT = 203   ' IBM Hebrew Supplement CP 862 Folded
  26.     CP_ISO = 204    ' ISO Hebrew 8859-8 Character Set
  27.     CP_H437 = 205   ' Ansi 437 codepage
  28.     CP_HMAC = 206   ' Macintosh Code Page
  29. '   CODE PAGES
  30.     CP_OEM_437 = 437
  31.     CP_ARABICDOS = 708
  32.     CP_DOS720 = 720
  33.     CP_DOS737 = 737
  34.     CP_DOS775 = 775
  35.     CP_IBM850 = 850
  36.     CP_IBM852 = 852
  37.     CP_DOS861 = 861
  38.     CP_DOS862 = 862
  39.     CP_IBM866 = 866
  40.     CP_DOS869 = 869
  41.     CP_THAI = 874
  42.     CP_EBCDIC = 875
  43.     CP_JAPAN = 932
  44.     CP_CHINA = 936
  45.     CP_KOREA = 949
  46.     CP_TAIWAN = 950
  47. '   UNICODE
  48.     CP_UNICODELITTLE = 1200
  49.     CP_UNICODEBIG = 1201
  50. '   CODE PAGES
  51.     CP_EASTEUROPE = 1250
  52.     CP_RUSSIAN = 1251
  53.     CP_WESTEUROPE = 1252
  54.     CP_GREEK = 1253
  55.     CP_TURKISH = 1254
  56.     CP_HEBREW = 1255
  57.     CP_ARABIC = 1256
  58.     CP_BALTIC = 1257
  59.     CP_VIETNAMESE = 1258
  60. '   KOREAN
  61.     CP_JOHAB = 1361
  62. '   MAC
  63.     CP_MAC_ROMAN = 10000
  64.     CP_MAC_JAPAN = 10001
  65.     CP_MAC_ARABIC = 10004
  66.     CP_MAC_GREEK = 10006
  67.     CP_MAC_CYRILLIC = 10007
  68.     CP_MAC_LATIN2 = 10029
  69.     CP_MAC_TURKISH = 10081
  70. '   CODE PAGES
  71.     CP_CHINESECNS = 20000
  72.     CP_CHINESEETEN = 20002
  73.     CP_IA5WEST = 20105
  74.     CP_IA5GERMAN = 20106
  75.     CP_IA5SWEDISH = 20107
  76.     CP_IA5NORWEGIAN = 20108
  77.     CP_ASCII = 20127
  78.     CP_RUSSIANKOI8R = 20866
  79.     CP_RUSSIANKOI8U = 21866
  80.     CP_ISOLATIN1 = 28591
  81.     CP_ISOEASTEUROPE = 28592
  82.     CP_ISOTURKISH = 28593
  83.     CP_ISOBALTIC = 28594
  84.     CP_ISORUSSIAN = 28595
  85.     CP_ISOARABIC = 28596
  86.     CP_ISOGREEK = 28597
  87.     CP_ISOHEBREW = 28598
  88.     CP_ISOTURKISH2 = 28599
  89.     CP_ISOLATIN9 = 28605
  90.     CP_HEBREWLOG = 38598
  91.     CP_USER = 50000
  92.     CP_AUTOALL = 50001
  93.     CP_JAPANNHK = 50220
  94.     CP_JAPANESC = 50221
  95.     CP_JAPANISO = 50222
  96.     CP_KOREAISO = 50225
  97.     CP_TAIWANISO = 50227
  98.     CP_CHINAISO = 50229
  99.     CP_AUTOJAPAN = 50932
  100.     CP_AUTOCHINA = 50936
  101.     CP_AUTOKOREA = 50949
  102.     CP_AUTOTAIWAN = 50950
  103.     CP_AUTORUSSIAN = 51251
  104.     CP_AUTOGREEK = 51253
  105.     CP_AUTOARABIC = 51256
  106.     CP_JAPANEUC = 51932
  107.     CP_CHINAEUC = 51936
  108.     CP_KOREAEUC = 51949
  109.     CP_TAIWANEUC = 51950
  110.     CP_CHINAHZ = 52936
  111.     CP_GB18030 = 54936
  112. '   UNICODE
  113.     CP_UTF7 = 65000
  114.     CP_UTF8 = 65001
  115. End Enum
  116. ' Flags
  117. Public Const MB_PRECOMPOSED = &H1
  118. Public Const MB_COMPOSITE = &H2
  119. Public Const MB_USEGLYPHCHARS = &H4
  120. Public Const MB_ERR_INVALID_CHARS = &H8
  121. Public Const WC_DEFAULTCHECK = &H100                ' check for default char
  122. Public Const WC_COMPOSITECHECK = &H200              ' convert composite to precomposed
  123. Public Const WC_DISCARDNS = &H10                    ' discard non-spacing chars
  124. Public Const WC_SEPCHARS = &H20                     ' generate separate chars
  125. Public Const WC_DEFAULTCHAR = &H40                  ' replace with default char
  126. Public Declare Function GetACP Lib "kernel32" () As Long
  127. Private Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, _
  128. ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, _
  129. ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long
  130. Private Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, _
  131. ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, _
  132. ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, _
  133. lpUsedDefaultChar As Long) As Long
  134. Public Function ANSItoUTF16(ByRef Text() As Byte, Optional ByVal cPage As KnownCodePage = CP_UNKNOWN, _
  135.                             Optional lFlags As Long) As Byte()
  136.     Static tmpArr() As Byte, textStr As String
  137.     Dim tmpLen As Long, textLen As Long, A As Long
  138.     If (Not Text) = True Then Exit Function
  139.     ' set code page to a valid one
  140.     If cPage = CP_UNKNOWN Then cPage = GetACP
  141.     If cPage = CP_ACP Or cPage = CP_WESTEUROPE Then
  142.         textLen = UBound(Text)
  143.         tmpLen = textLen + textLen + 1
  144.         If (Not tmpArr) = True Then ReDim Preserve tmpArr(tmpLen)
  145.         If UBound(tmpArr) <> tmpLen Then ReDim Preserve tmpArr(tmpLen)
  146.         For A = 0 To UBound(Text)
  147.             tmpArr(A + A) = Text(A)
  148.         Next A
  149.     Else
  150.         textStr = CStr(Text) & "|"
  151.         textLen = LenB(textStr)
  152.         tmpLen = textLen + textLen
  153.         ReDim Preserve tmpArr(tmpLen + 1)
  154.         ' get the new string to tmpArr
  155.         tmpLen = MultiByteToWideChar(CLng(cPage), lFlags, ByVal StrPtr(textStr), -1, _
  156.                                      ByVal VarPtr(tmpArr(0)), tmpLen)
  157.         If tmpLen = 0 Then Exit Function
  158.         tmpLen = tmpLen + tmpLen - 5
  159.         'If tmpArr(tmpLen - 1) = 0 And tmpArr(tmpLen) = 0 Then tmpLen = tmpLen - 2
  160.         If UBound(tmpArr) <> tmpLen Then ReDim Preserve tmpArr(tmpLen)
  161.     End If
  162.     ' return the result
  163.     ANSItoUTF16 = tmpArr
  164. End Function
  165. Public Function UTF16toANSI(ByRef Text() As Byte, Optional ByVal cPage As KnownCodePage = CP_UNKNOWN, _
  166.                             Optional lFlags As Long) As Byte()
  167.     Static tmpArr() As Byte
  168.     Dim tmpLen As Long, textLen As Long, A As Long
  169.     If (Not Text) = True Then Exit Function
  170.     ' set code page to a valid one
  171.     If cPage = CP_UNKNOWN Then cPage = GetACP
  172.     If cPage = CP_ACP Or cPage = CP_WESTEUROPE Then
  173.         textLen = UBound(Text)
  174.         tmpLen = (textLen + 1) \ 2 - 1
  175.         If (Not tmpArr) = True Then ReDim Preserve tmpArr(tmpLen)
  176.         If UBound(tmpArr) <> tmpLen Then ReDim Preserve tmpArr(tmpLen)
  177.         For A = 0 To tmpLen
  178.             tmpArr(A) = Text(A + A)
  179.         Next A
  180.     Else
  181.         textLen = (UBound(Text) + 1) \ 2
  182.         ' at maximum ANSI can be four bytes per character in new Chinese encoding GB18030–2000
  183.         tmpLen = textLen + textLen + textLen + textLen + 1
  184.         ReDim Preserve tmpArr(tmpLen - 1)
  185.         ' get the new string to tmpArr
  186.         tmpLen = WideCharToMultiByte(CLng(cPage), lFlags, ByVal VarPtr(Text(0)), textLen, ByVal VarPtr(tmpArr(0)), _
  187.                                      tmpLen, ByVal 0&, ByVal 0&)
  188.         If tmpLen = 0 Then Exit Function
  189.         ' a hopeless try to correct a weird error?
  190.         ReDim Preserve tmpArr(tmpLen - 1)
  191.     End If
  192.     ' return the result
  193.     UTF16toANSI = tmpArr
  194. End Function

Last edited by si_the_geek; Jun 17th, 2008 at 07:23 AM. Reason: updated link to controls
Merri is offline   Reply With Quote
Old Mar 16th, 2006, 06:39 PM   #2
freshblueO2
New Member
 
Join Date: Mar 06
Posts: 3
freshblueO2 is an unknown quantity at this point (<10)
Arrow Re: Classic VB - Does Visual Basic 6 support Unicode?

Let me provide an alternative. You can use Office 2000 activeX controls, otherwise known as the Forms 2.0 (FM20.dll) I use in all the senerios (at least I think I have) that you mentioned.

But you say "But I have to purchase Office 2000 in order to use it. My clients will have to purchase Office 2000 to use it." Nope, luckily you and they don't have to. Microsoft provided a legal free version of using the control, but you have to download and install a program to do so...

READ HERE -> INFO: Usage and Redistribution of FM20.DLL
Download -> MS ActiveX Control Pad
freshblueO2 is offline   Reply With Quote
Old Dec 4th, 2009, 11:08 AM   #3
LaVolpe
VBaholic & Loving It
 
LaVolpe's Avatar
 
Join Date: Oct 07
Location: GetWindowRect()
Posts: 7,668
LaVolpe is a name known to all (1000+)LaVolpe is a name known to all (1000+)LaVolpe is a name known to all (1000+)LaVolpe is a name known to all (1000+)LaVolpe is a name known to all (1000+)LaVolpe is a name known to all (1000+)LaVolpe is a name known to all (1000+)LaVolpe is a name known to all (1000+)LaVolpe is a name known to all (1000+)
Re: Classic VB - Does Visual Basic 6 support Unicode?

Quote:
Originally Posted by Merri View Post
... The worst news is that VB6 controls use ANSI. The VB propertybags can't hold Unicode data
Though that is a true statement, there is a relatively easy workaround for storing unicode in a propertybag, i.e., usercontrols. VB can store 1 dimensional byte arrays in propertybags.

Let's say that a string variable m_Text contains unicode data. To store and read the data via a userconrol's propertybag, one can do this:
vb Code:
  1. Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
  2.  
  3. Dim m_Text As String
  4.  
  5. Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
  6.     Dim bData() As Byte, tLen As Long
  7.     If m_Text <> vbNullString Then
  8.         tLen = LenB(m_Text)
  9.         ReDim bData(0 To tLen - 1)
  10.         CopyMemory bData(0), ByVal StrPtr(m_Text), tLen
  11.         PropBag.WriteProperty "Text", bData()
  12.     End If
  13. End Sub
  14.  
  15. Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
  16.     Dim bData() As Byte, tLen As Long
  17.     bData() = PropBag.ReadProperty("Text", vbNullString)
  18.     tLen = UBound(bData) + 1
  19.     If tLen = 0 Then
  20.        m_Text = vbNullString
  21.     Else
  22.        m_Text = String$(tLen \ 2, vbNullChar)
  23.        CopyMemory ByVal StrPtr(m_Text), bData(0), tLen
  24.     End If
  25. End Sub
__________________
Insomnia is just a byproduct of, "It can't be done"
Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum. Read the HitchHiker's Guide to Getting Help on the Forums.

{Memory Leak FAQ} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor} {VBA Control Arrays}
{XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

Last edited by LaVolpe; Dec 7th, 2009 at 08:52 AM. Reason: clarify content
LaVolpe is offline   Reply With Quote
Reply

Go Back   VBForums > Visual Basic > Visual Basic FAQs


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On

Forum Jump


All times are GMT -5. The time now is 08:08 PM.





Acceptable Use Policy

Internet.com
The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers

Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.