• Thứ Ba, 06/04/2004 09:45 (GMT+7)

    Câu hỏi :
    Xin hỏi có cách nào hiển thị được Unicode trong Access2000 chạy trên Win98 không?

    Trả lời :

    Hiện nay, chuẩn tiếng Việt TCVN 6609 của nước ta qui định dùng mã Unicode để biểu diễn văn bản tiếng Việt, do đó nhu cầu lập trình ứng dụng xử lý và hiển thị được chuỗi văn bản Unicode là rất phổ biến. Tuy nhiên, hầu hết các người lập trình đều gặp khó khăn trong việc hiện thực các ứng dụng hỗ trợ mã Unicode. Do đó sẵn câu hỏi của bạn, chúng tôi sẽ trình bày hiện trạng lập trình xử lý mã Unicode trong VB.

    Trước hết bạn nên phân biệt 2 khái niệm: một là ngôn ngữ lập trình VB và hai là môi trường lập trình trực quan VB. Bản thân ngôn ngữ VB từ version 5.0 trở về sau hỗ trợ rất tốt chuỗi ký tự Unicode, thật vậy các chuỗi ký tự trong chương trình khả thi được dịch từ source code VB đều được miêu tả dưới dạng Unicode UCS-2. Tuy nhiên, chỉ có môi trường lập trình VB .Net mới hỗ trợ nhập chuỗi Unicode UCS-2 trực tiếp cho các phần tử giao diện cũng như trong cửa sổ viết source code, còn các môi trường lập trình VB 6.0 trở về trước thì không cho phép nhập chuỗi Unicode UCS-2 trực tiếp cho các phần tử giao diện cũng như trong cửa sổ viết source code. Do đó nếu muốn viết các ứng dụng hiển thị chuỗi Unicode một cách trực quan dễ dàng, bạn nên dùng môi trường lập trình VB .Net. Còn nếu bạn vẫn muốn tiếp tục dùng VB 6.0 trở về trước chạy trên Win9x và WinMe, bạn vẫn có thể viết các ứng dụng hiển thị chuỗi Unicode trong các phần tử giao diện với 1 số lưu ý sau đây:

    1. Vì môi trường VB 6.0 trở về trước không cho phép nhập chuỗi Unicode UCS-2 trực tiếp vào các phần tử giao diện cũng như trong source code của ứng dụng nên bạn buộc phải nhập chuỗi Unicode dưới dạng UTF-8 (vì dạng UTF-8 tương thích tốt với chuỗi ASCII truyền thống).

    2. Khi chương trình chạy, bạn cần đổi các chuỗi UTF-8 thành dạng Unicode UCS-2 bên trong để được xử lý và hiển thị tốt. Windows có cung cấp 1 hàm API để phục vụ việc chuyển đổi này, đó là hàm MultiByteToWideChar(). Thông thường để gọi hàm API trong module VB, bạn cần khai báo đặc tả hàm API cần gọi bằng lệnh Declare, thí dụ đối với hàm MultiByteToWideChar(), bạn cần khai báo nó như sau :

    Private Declare Function MultiByteToWideChar Lib 'kernel32' Alias 'MultiByteToWideChar' (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As String, ByVal cchMultiByte As Long, ByVal lpWideCharStr As String, ByVal cchWideChar As Long) As Long

    Tuy nhiên do cơ chế gởi/nhận các tham số thuộc kiểu String của VB khá đặc biệt: luôn đổi chuỗi ký tự VB từ Unicode sang dạng ANSI để gởi cho hàm API và luôn xem chuỗi trả lại có dạng ANSI nên VB tự động chuyển chuỗi trả về sang Unicode trước khi dùng. Cơ chế chuyển đổi chuỗi tự động như trên sẽ làm chuỗi trả về (theo tham số lpWideCharStr) bởi hàm MultiByteToWideChar() sẽ bị hư vì bản thân nó đã là chuỗi Unicode, nhưng VB cứ xem nó như chuỗi ANSI và đổi thêm lần nữa sang Unicode. Cách khắc phục vấn đề trên là không được dùng lệnh Declare để khai báo hàm  MultiByteToWideChar() như trên mà phải dùng thư viện kiểu (TypeLib) để khai báo hàm MultiByteToWideChar(). Qui trình tạo thư viện kiểu chứa hàm MultiByteToWideChar() gồm các bước sau :

      viết đặc tả thư viện TypeLib chứa hàm MultiByteToWideChar() bằng ngôn ngữ ODL như sau (dùng trình soạn thảo văn bản bất kỳ, cất nội dung lên file uniutil.odl) :

    [

       uuid(13C9AF40-856A-101B-B9C2-04021C007002),

       helpstring('WIDE Windows API Type Library')

    ]

    library WideWin32API

    {

       [

          helpstring('KERNEL API Calls'),

          dllname('KERNEL32')

       ]

       module KernelAPI

       {

          [

             helpstring('Convert a UTF8 string to a UCS-2 string.'),

             entry('MultiByteToWideChar')

          ]

          long _stdcall MultiByteToWideChar

          (

             [in]  long CodePage,

             [in]  long dwFlags,

             [in]  BSTR lpMultiByteStr,

             [in]  long cchMultiByte,

             [in]  BSTR lpWideCharStr,

             [in]  long cchWideChar

          );

       };

       };

      dịch file ODL ở trên thành file thư viện kiểu uniutil.tlb bằng tiện ích mktyplib.exe. Để có tiện ích này, bạn có thể cài bộ Visual Studio 6.0, nếu cài ở chế độ Typical, bộ VS sẽ được cài vào thư mục 'c:\Program Files\Microsoft Visual Studio'. Nếu vậy, để dịch file uniutil.odl ở trên, bạn hãy tạo 1 cửa sổ DOS Prompt, dùng lệnh cd để chuyển về thư mục chứa file uniutil.odl, rồi nhập tuần tự 2 lệnh sau để dịch nó:

    c:\progra~1\micros~3\vc98\bin\vcvars32.bat

    mktyplib /I c:\progra~1\micros~3\vc98\include /win32 /tlb uniutil.idl uniutil.odl

    Giả sử tên ngắn của thư mục 'Program Files' là 'progra~1', của thư mục 'Microsoft Visual Studio' là 'micros~3'. Để gọi hàm trong thư viện kiểu uniutil.tlb từ project VB, bạn hãy chọn menu Project.References... để hiển thị cửa sổ References, ấn button Browse rồi duyệt hệ thống file để chọn file uniutil.tlb. Sau khi đã 'add' thư viện kiểu uniutil.tlb, bạn có thể gọi bất kỳ hàm nào trong thư viện đó mà không cần phải dùng lệnh Declare nữa.

    3. các phần tử CommandButton, Label, TextBox,... chuẩn của VB không thể hiển thị được chuỗi Unicode, do đó bạn phải dùng các phần tử giao diện tương ứng trong Control 'Microsoft Forms 2.0 Object Library'. Để dùng được các phần tử giao diện mới này trong 1 Project VB, bạn hãy ấn chuột phải vào chỗ trống trong cửa sổ ToolBox, chọn mục 'Components...' để hiển thị cửa sổ 'Components', ấn button Controls, duyệt đến mục 'Microsoft Forms 2.0 Object Library' và chọn nó để thêm các phần tử giao diện trong thư viện này vào Toolbox của Project VB hầu có thể dùng nó trong các form giao diện.

    Để cho bạn thấy rõ hơn việc hiển thị tiếng Việt Unicode trong các phần tử giao diện của VB, chúng tôi sẽ trình bày qui trình viết 1 ứng dụng VB nhỏ gồm 1 form, form này chứa 4 phần tử: 1 CommandButton có caption là 'Bắt đầu', 1 Label có caption 'Hãy nhập tên của bạn vào TextBox ngay dưới đây :' , 1 textbox để nhập chuỗi Unicode, 1 textbox khác để demo việc copy chuỗi Unicode từ textnox này sang textbox kia.

    o  trước hết hãy tạo file thư viện kiểu uniutil.tlb như đã trình bày ở trên.

    chạy VB, tạo mới 1 Project 'Standard EXE'.

    o  ấn chuột phải vào chỗ trống trong cửa sổ ToolBox, chọn mục 'Components...' để hiển thị cửa sổ 'Components', ấn button Controls, duyệt đến mục 'Microsoft Forms 2.0 Object Library' và chọn nó để thêm các phần tử giao diện trong thư viện này vào Toolbox của Project VB.

    chọn menu Project.References... để hiển thị cửa sổ References, ấn button Browse rồi duyệt hệ thống file để chọn file uniutil.tlb để thêm nó vào Project.

      vẽ lần lượt từng phần tử: Label với caption 'Hãy nhập tên của bạn vào TextBox ngay dưới đây :' và tên mặc định là Label1, 1 TextBox với tên mặc định là TextBox1, CommandButton với caption 'Bắt đầu' và tên mặc định là CommandButton1, 1 TextBox nữa với tên mặc định là TextBox2. Lưu ý rằng bạn phải dùng trình hỗ trợ tiếng Việt có khả năng tạo mã UTF-8 (VietKey 2000, GVSBK 2.2,...) và chọn mã này trong việc nhập các chuỗi tiếng Việt trong lúc thiết kế Form. Cũng lưu ý rằng các phần tử cần vẽ là các phần tử của thư viện 'Microsoft Forms 2.0 Object Library', chứ không phải là các phần tử VB chuẩn (thường chúng nằm phía dưới cùng trong cửa sổ ToolBox). Sau khi thiết kế xong, Form sẽ có dạng sau (chú ý các chuỗi UTF-8 rất khó đọc) :

      tạo thủ tục xử lý sự kiện Click chuột cho phần tử CommandButton1 rồi vào cửa sổ viết code của Form để nhập đoạn chương trình sau:

    Option Explicit

    ' Thủ tục khởi động Form

    Private Sub Form_Load()

    Dim s As String

    Dim x() As Byte

    Dim ret As Integer

       ' Chuyển caption của CommandButton1 về Unicode

       x = StrConv(CommandButton1.Caption, vbFromUnicode)

       ret = MultiByteToWideChar(65001, 0, x, -1, s, 0)

       s = Space(ret)

       ret = MultiByteToWideChar(65001, 0, x, -1, s, ret)

       CommandButton1.Caption = s

       ' Chuyển caption của Label1 về Unicode

       x = StrConv(Label1.Caption, vbFromUnicode)

       ret = MultiByteToWideChar(65001, 0, x, -1, s, 0)

       s = Space(ret)

       ret = MultiByteToWideChar(65001, 0, x, -1, s, ret)

       Label1.Caption = s

    End Sub

     

    ' Thủ tục xử lý sự kiện Click CommandButton1

    Private Sub CommandButton1_Click()

        ' thử copy nội dung từ TextBox1 sang TextBox2

        TextBox2.Text = TextBox1.Text

        ' thử copy nội dung từ TextBox1 sang Title của Form

        Form1.Caption = TextBox1.Text

    End Sub

    Khi chạy Form được hiển thị như sau (các chuỗi Unicode đều hiển thị đúng) :

    Khi bạn nhập tên mình hay 1 chuỗi Unicode bất kỳ (nhớ thiết lập trình hỗ trợ tiếng Việt về chế độ tạo mã Unicode dựng sẵn), rồi ấn button thì dữ liệu ở TextBox1 sẽ được copy sang TextBox2, cửa sổ của Form sẽ như sau (nếu bạn nhập 'Nguyễn Văn Hiệp'). 


    Lưu ý rằng chỉ có TextBox2 (đối tượng của thư viện Form 2.0) mới hiển thị đúng tiếng Việt Unicode, còn title của Form thì không vì Form chuẩn VB không hỗ trợ mã Unicode (các ký tự Unicode có mã >=256 đều bị đổi thành dấu ?).

     

    Chuyên mục: Lập trình