# Visual Basic > Visual Basic FAQs >  Classic VB - How to use Unicode with forms and standard controls?

## Merri

You've probably heard many times that VB6 native controls don't support Unicode. For the most part this is true, there simply is no way to make a label or textbox to truly show Unicode.

There is however a possibility with forms and some of the controls for Unicode. Namely the controls are CheckBox, CommandButton, Frame and OptionButton. All four of these are based on the same internal Windows Button control, even if VB6 separates them. The actual trick is simple: use Unicode version of the default window procedure instead of VB's own methods.

The following code lets you pass in any form or control, paste into a module:

```
' UniCaption
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 Const WM_GETTEXT = &HD
Private Const WM_GETTEXTLENGTH = &HE
Private Const WM_SETTEXT = &HC

Public Property Get UniCaption(ByRef Control As Object) As String
    Dim lngLen As Long, lngPtr As Long
    ' validate supported control
    If Not Control Is Nothing Then
        If _
            (TypeOf Control Is CheckBox) _
        Or _
            (TypeOf Control Is CommandButton) _
        Or _
            (TypeOf Control Is Form) _
        Or _
            (TypeOf Control Is Frame) _
        Or _
            (TypeOf Control Is MDIForm) _
        Or _
            (TypeOf Control Is OptionButton) _
        Then
            ' get length of text
            lngLen = DefWindowProcW(Control.hWnd, WM_GETTEXTLENGTH, 0, ByVal 0)
            ' must have length
            If lngLen Then
                ' create a BSTR of that length
                lngPtr = SysAllocStringLen(0, lngLen)
                ' make the property return the BSTR
                PutMem4 ByVal VarPtr(UniCaption), ByVal lngPtr
                ' call the default Unicode window procedure to fill the BSTR
                DefWindowProcW Control.hWnd, WM_GETTEXT, lngLen + 1, ByVal lngPtr
            End If
        Else
            ' go ahead and try the default property
            On Error Resume Next
            UniCaption = Control
        End If
    End If
End Property
Public Property Let UniCaption(ByRef Control As Object, ByRef NewValue As String)
    ' validate supported control
    If Not Control Is Nothing Then
        If _
            (TypeOf Control Is CheckBox) _
        Or _
            (TypeOf Control Is CommandButton) _
        Or _
            (TypeOf Control Is Form) _
        Or _
            (TypeOf Control Is Frame) _
        Or _
            (TypeOf Control Is MDIForm) _
        Or _
            (TypeOf Control Is OptionButton) _
        Then
            ' call the default Unicode window procedure and pass the BSTR pointer
            DefWindowProcW Control.hWnd, WM_SETTEXT, 0, ByVal StrPtr(NewValue)
        Else
            ' go ahead and try the default property
            On Error Resume Next
            Control = NewValue
        End If
    End If
End Property
```

The usage is simple, UniCaption(Form1) = ChrW$(&H3042) will display a single Japanese character as the caption of Form1 (*important!* you need Far East Character Support installed via Control Panel to see Japanese!). The end result is Unicode instead of the infamous question mark in Windows XP and Windows Vista. However, this trick does not unfortunatenaly work in Windows 2000. Windows 2000 does display the Unicode character in the taskbar, but fails to draw the actual window caption correctly. There is no easy workaround for this.


When working with MDI forms things get a bit more complicated if you happen to support maximized child forms: VB updates the MDI form's caption automatically when a child form is maximized or a maximized state of a child is removed. Thus you need to do a custom function that updates the MDI caption whenever you want it to be updated.



```
' MDI form sample
Option Explicit

Public Sub CaptionW(Optional ByRef NewCaption As String)
    ' update to new caption if a non vbNullString was passed
    If StrPtr(NewCaption) Then Me.Tag = NewCaption
    ' must have active form
    If Not Me.ActiveForm Is Nothing Then
        ' see if window state is maximized
        If Me.ActiveForm.WindowState = vbMaximized Then
            ' show both child caption and MDI caption
            UniCaption(Me) = UniCaption(Me.ActiveForm) & " - " & Me.Tag
        Else
            ' show only MDI caption
            UniCaption(Me) = Me.Tag
        End If
    Else
        ' show only MDI caption
        UniCaption(Me) = Me.Tag
    End If
End Sub

Private Sub MDIForm_Load()
    ' set initial caption
    Me.CaptionW "MDI: " & ChrW$(&H3042)
End Sub
```

The code looks for the current active child form, gets it's actual caption and then shows it alongside the MDI form's own caption that is being stored in the Tag property of the MDI form. If the child form is not maximized, the MDI caption will not contain the child form's caption.


In MDI child form we need to do a bit of coding as well:

```
' MDI child form sample
Option Explicit

Private Sub Form_Load()
    Dim Ctrl As Control
    ' attempt to change caption of all controls
    For Each Ctrl In Me.Controls
        UniCaption(Ctrl) = ChrW$(&H3042) & ChrW$(&H3052) & ChrW$(&H3062)
    Next Ctrl
    ' change the form's caption
    UniCaption(Me) = "Child: " & ChrW$(&H3042)
End Sub

Private Sub Form_Resize()
    Static WindowState As FormWindowStateConstants
    ' see if window state has changed
    If WindowState <> Me.WindowState Then
        ' use custom caption updating in MDI form
        MDIForm1.CaptionW
        ' remember current window state
        WindowState = Me.WindowState
    End If
End Sub

Private Sub Form_Unload(Cancel As Integer)
    ' important if you allow maximized MDI child style!
    ' otherwise the ANSI caption appears and there is no easy way to detect when that happens
    Me.Visible = False
End Sub
```

Basically the code attempts to change the caption of all controls, detects for window state changes to know when to change MDI parent caption and fixes a maximized child window unload behavior with the MDI parent window so that a correct caption is shown when the child is unloaded.


A full sample project is attached. It has a bit more meat into it and should get anyone started with Unicode in VB6. The project includes Unicode versions of Command$ and MsgBox functions, so you can also easily get the Unicode filenames upon application startup and show true Unicode message boxes.

*Included functions/properties/subs:*
UniInteraction.bas: Command, IIf and MsgBox
UniStrings.bas: QuickSplit, QuickSplitB, SplitToVar and UniCaption

----------


## tanjiunnyann

Wow!!! Unicaption for the control works perfectly!!!!!
I can even do like this way instead of ChrW$():

UniCaption(cmdButton1) = "我們都是好朋友"

In the non Chinese OS System also shows correctly!! Thanks Merri!

----------


## vb56390

Hi, there is some problem

when I replaced  "ChrW$(&H3042) & ChrW$(&H3052) & ChrW$(&H3062)"  to "ChrW$(&H2632) & ChrW$(&H2633) & ChrW$(&H2634)" the contrl's caption didn't work correct, it just shows "???".

----------

