VisualBasic6編程中的漢字處理

字號:

在DOS時(shí)代,擁有一個(gè)華麗的漢字菜單幾乎是每個(gè)高檔中文應(yīng)用程序必須的包裝。中文Windows操作系統(tǒng)的出現(xiàn)使得高級開發(fā)平臺實(shí)現(xiàn)全中文的提示和界面非常容易和方便。在一般的應(yīng)用程序中已經(jīng)很少需要去專門考慮漢字處理的問題。
    但是在許多工程控制和字符串處理的環(huán)境中,漢字字符的處理仍然有別于西文字符的處理,需要加以專門的考慮。
    一、VB6對漢字處理的支持
    對漢字處理,VB6主要是提供了一些輸入法設(shè)置方面的支持。它提供了一個(gè)ImeMode屬性和ImeStatus函數(shù)來確定和設(shè)置輸入法的狀態(tài)。而且此屬性和方法只在VB6的東亞區(qū)版本中有效。
    IMEStatus函數(shù)返回一個(gè)整數(shù),用來指定當(dāng)前Windows的輸入法(IME)方式。
    下面是中文地區(qū)的返回值:
    常數(shù) 值 描述
    vbIMENoOP 0 不安裝IME(缺省)
    vbIMEOn 1 打開IME
    ImeMode屬性返回或者設(shè)置被選定的對象的 IME (Input Method Editor,輸入方法編輯器)狀態(tài)。
    可以先用ImeStatus函數(shù)來檢測當(dāng)前的輸入狀態(tài),并用IMEMode來控制其輸入狀態(tài)。
    如Text1.IMEMode=0(預(yù)定值)、=1(切換為中文輸入)、=2(切換為英文輸入)
    對于簡體漢字和繁體漢字 IME,只能使用設(shè)置 0 到 2。設(shè)置 3 到 10 對于漢字系統(tǒng)是無效的。
    VB6功能上對漢字處理的直接支持也僅限于此。對于漢字字符串的處理,VB6并沒有提供專門的函數(shù)和方法。
    二、確定漢字字符串的長度
    各個(gè)版本的VB對漢字字符的長度定義并不相同。在Windows 3.x中,VB3中認(rèn)為每個(gè)漢字的長度為2字節(jié)。VB自從32位版本以後,不管中英文字,均以2 bytes來儲存,這與中文Win95的漢字內(nèi)核有關(guān)。但是VB4以后,VB認(rèn)為每個(gè)漢字的長度為1。這在處理包含漢字的字符串時(shí)帶來很多的不便。
    由于Len、Left、Mid等字符串函數(shù)認(rèn)為一個(gè)漢字和一個(gè)西文字符的長度都為1,因此處理漢字字符串時(shí)有一定的難度。實(shí)現(xiàn)上必須要能把漢字按照兩個(gè)字符(字節(jié))的形式讀出。因此在截取漢字字符串的子串時(shí)需特別注意。
    由于漢字處理和漢字字模存儲的特殊性,在許多情況下我們希望漢字字符的長度為2,英文字符為1。由于VB5和VB6把一個(gè)漢字作為一個(gè)字符。因此處理漢字時(shí)首先必須能正確判斷漢字字符串的長度。
    在VB3或C++里,漢字的 ASCII碼均大于零,而VB5和VB6中漢字的ASCII碼小于0。因此通過判斷一個(gè)未知字符的ASCII碼就可以判斷該字符是否漢字。
    這里我們提供了兩種方法來判斷漢字字符串的長度。
    1、方法1
    VB6中提供了LenB函數(shù)用于字符串中的字節(jié)數(shù)據(jù)。如同在雙字節(jié)字符集(DBCS)語言中一樣,LenB返回的是用于代表字符串的字節(jié)數(shù),而不是返回字符串中字符的數(shù)量。如為用戶自定義類型,LenB返回在內(nèi)存中的大小。
    LenB(StrConv(Str1,vbFormUnicode))
    對要處理的字符串Str1,必須先使用StrConv函數(shù)把ANSI格式的Byte數(shù)組轉(zhuǎn)換為字符串,否則直接使用LenB函數(shù)得到的結(jié)果比實(shí)際結(jié)果大。
    2、方法2
    這里自定義了一個(gè)子函數(shù)CLen來計(jì)算漢字字符串的實(shí)際長度。同時(shí)還能判斷字符串中漢字的實(shí)際個(gè)數(shù)。
    Function CLen(HzStr$) as Integer
    Static HzNum as Integer
    L = len(HzStr$)
    For n=1 to L
    If Asc(mid$( HzStr$,n,1))<0 Then HzNum = HzNum + 1
    Next n
    Clen = L + HzNum
    End Function
    CLen函數(shù)中的靜態(tài)變量HzNum返回字符串中實(shí)際漢字的數(shù)目。
    三、漢字字模讀寫和存儲的機(jī)理
    計(jì)算機(jī)是以編碼的方式來處理和使用字符的。西文字符采用一個(gè)字節(jié)表示,即ASCII碼,一般只用七位來表示128個(gè)字符,而把位用作奇偶校驗(yàn)(或者不用)。我國國標(biāo)規(guī)定漢字用內(nèi)碼表示,內(nèi)碼為兩個(gè)字節(jié)。為了保證中西文兼容,也就是說漢字系統(tǒng)的內(nèi)碼必須同時(shí)允許ASCII碼和漢字的使用,兩者之間不應(yīng)發(fā)生沖突。目前規(guī)定每個(gè)字節(jié)只用七位,若兩個(gè)字節(jié)的位均為1,則該字符為漢字。
    國標(biāo)對漢字字庫的結(jié)構(gòu)作了統(tǒng)一規(guī)定,即將字庫分成若干個(gè)區(qū),每個(gè)區(qū)有94個(gè)漢字,每個(gè)漢字在字庫中有確定的區(qū)和位,因此每個(gè)漢字各有一個(gè)區(qū)位碼,知道了區(qū)位碼也就相當(dāng)于知道了漢字在字庫中的位置。由于漢字的內(nèi)碼與區(qū)位碼有一定的關(guān)系,所以只要通過漢字的內(nèi)碼就可得到該漢字的區(qū)位碼,也就得到了該漢字的字模。
    查找一個(gè)漢字字模數(shù)據(jù)的算法為:
    漢字內(nèi)碼 -> 區(qū)位碼 -> 記錄號 -> 字模數(shù)據(jù)
    一個(gè)16點(diǎn)陣漢字其字模數(shù)據(jù)共有32字節(jié),可以看作是一條記錄,在程序中可以用一個(gè)數(shù)組存放。在DOS的圖形模式下,漢字是通過描點(diǎn)的方法逐點(diǎn)畫上去的。讀取字模中每個(gè)字節(jié)的每一位,就能確定漢字中的每個(gè)點(diǎn)。故一個(gè)16×16點(diǎn)陣的漢字必須要32個(gè)字節(jié)的字模數(shù)據(jù)才能確定。
    以下是DOS的圖形模式下顯示一個(gè)16×16點(diǎn)陣漢字時(shí)的描點(diǎn)順序圖。每兩個(gè)字節(jié)的字模數(shù)據(jù)確定一行。
    四、VB6中實(shí)現(xiàn)漢字字模轉(zhuǎn)換的技巧
    在許多工程控制的應(yīng)用環(huán)境中,經(jīng)常需要對標(biāo)準(zhǔn)的漢字字模進(jìn)行調(diào)整和轉(zhuǎn)換。
    要對漢字字模進(jìn)行轉(zhuǎn)換首先應(yīng)該正確地讀出16點(diǎn)陣漢字在字庫中的32字節(jié)的字模數(shù)據(jù)。設(shè)某一漢字的內(nèi)碼為ddff,其中dd表示區(qū)內(nèi)碼,ff表示位內(nèi)碼,則dd-&Ha1為該漢字的區(qū)碼,ff-&Ha1為該漢字的位碼。則該漢字在字庫中的位置為:
    Location = [(dd-&Ha1)×94 + (ff-&Ha1)]×32
    需要注意的是,以何種方式從字庫文件中讀取這32字節(jié)也是一個(gè)關(guān)鍵問題。由于二進(jìn)制(Binary)方式訪問文件可以直接查看文件中指定的字節(jié),而且二進(jìn)制方式也是支持用戶到文件的任何位置讀寫任意長度數(shù)據(jù)的方法。因而以二進(jìn)制方式打開漢字字庫文件是最適合的。
    VB6雖然提供了較強(qiáng)的位運(yùn)算功能,但是對于在字模轉(zhuǎn)換中使用較多的移位操作,卻沒有提供對應(yīng)的移位運(yùn)算符、指令或函數(shù)。其實(shí)通過and(與)、or(或)二個(gè)位運(yùn)算符即可編制一個(gè)自定義子函數(shù)來實(shí)現(xiàn)移位運(yùn)算。