Results 1 to 3 of 3

Thread: Classic VB - How to use Unicode with forms and standard controls?

  1. #1

    Thread Starter
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Classic VB - How to use Unicode with forms and standard controls?

    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:
    Code:
    ' 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.

    Code:
    ' 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:
    Code:
    ' 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
    Attached Files Attached Files
    Last edited by Merri; Sep 13th, 2008 at 01:26 PM.

  2. #2
    Junior Member
    Join Date
    Sep 2008
    Posts
    26

    Re: Classic VB - How to use Unicode with forms and standard controls?

    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!

  3. #3
    Lively Member
    Join Date
    Dec 2016
    Posts
    86

    Re: Classic VB - How to use Unicode with forms and standard controls?

    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 "???".

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width