在DOS时代,拥有一个华丽的汉字菜单几乎是每个高档中文应用程序必须的包装。中文Windows操作系统的出现使得高级开发平台实现全中文的提示和界面非常容易和方便。在一般的应用程序中已经很少需要去专门考虑汉字处理的问题。

  但是在许多工程控制和字符串处理的环境中,汉字字符的处理仍然有别于西文字符的处理,需要加以专门的考虑。

  一、VB6对汉字处理的支持

  对汉字处理,VB6主要是提供了一些输入法设置方面的支持。它提供了一个ImeMode属性和ImeStatus函数来确定和设置输入法的状态。而且此属性和方法只在VB6的东亚区版本中有效。

  IMEStatus函数返回一个整数,用来指定当前Windows的输入法(IME)方式。

  下面是中文地区的返回值:

  常数
值 描述

  vbIMENoOP 0 不安装IME(缺省)

  vbIMEOn 1
打开IME

  ImeMode属性返回或者设置被选定的对象的 IME (Input Method
Editor,输入方法编辑器)状态。

  可以先用ImeStatus函数来检测当前的输入状态,并用IMEMode来控制其输入状态。

  如Text1.IMEMode=0(预定值)、=1(切换为中文输入)、=2(切换为英文输入)

  对于简体汉字和繁体汉字
IME,只能使用设置 0 到 2。设置 3 到 10
对于汉字系统是无效的。

  VB6功能上对汉字处理的直接支持也仅限于此。对于汉字字符串的处理,VB6并没有提供专门的函数和方法。

  二、确定汉字字符串的长度

  各个版本的VB对汉字字符的长度定义并不相同。在Windows
3.x中,VB3中认为每个汉字的长度为2字节。VB自从32位版本以後,不管中英文字,均以2
bytes来储存,这与中文WinArray5的汉字内核有关。但是VB4以后,VB认为每个汉字的长度为1。这在处理包含汉字的字符串时带来很多的不便。

  由于Len、Left、Mid等字符串函数认为一个汉字和一个西文字符的长度都为1,因此处理汉字字符串时有一定的难度。实现上必须要能把汉字按照两个字符(字节)的形式读出。因此在截取汉字字符串的子串时需特别注意。

  由于汉字处理和汉字字模存储的特殊性,在许多情况下我们希望汉字字符的长度为2,英文字符为1。由于VB5和VB6把一个汉字作为一个字符。因此处理汉字时首先必须能正确判断汉字字符串的长度。

  在VB3或C++里,汉字的
ASCII码均大于零,而VB5和VB6中汉字的ASCII码小于0。因此通过判断一个未知字符的ASCII码就可以判断该字符是否汉字。

  这里我们提供了两种方法来判断汉字字符串的长度。

  1、方法1

  VB6中提供了LenB函数用于字符串中的字节数据。如同在双字节字符集(DBCS)语言中一样,LenB返回的是用于代表字符串的字节数,而不是返回字符串中字符的数量。如为用户自定义类型,LenB返回在内存中的大小。

  LenB(StrConv(Str1,vbFormUnicode))

  对要处理的字符串Str1,必须先使用StrConv函数把ANSI格式的Byte数组转换为字符串,否则直接使用LenB函数得到的结果比实际结果大。

  2、方法2

  这里自定义了一个子函数CLen来计算汉字字符串的实际长度。同时还能判断字符串中汉字的实际个数。

  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函数中的静态变量HzNum返回字符串中实际汉字的数目。

  三、汉字字模读写和存储的机理

  计算机是以编码的方式来处理和使用字符的。西文字符采用一个字节表示,即ASCII码,一般只用七位来表示128个字符,而把最高位用作奇偶校验(或者不用)。我国国标规定汉字用内码表示,内码为两个字节。为了保证中西文兼容,也就是说汉字系统的内码必须同时允许ASCII码和汉字的使用,两者之间不应发生冲突。目前规定每个字节只用七位,若两个字节的最高位均为1,则该字符为汉字。

  国标对汉字字库的结构作了统一规定,即将字库分成若干个区,每个区有Array4个汉字,每个汉字在字库中有确定的区和位,因此每个汉字各有一个区位码,知道了区位码也就相当于知道了汉字在字库中的位置。由于汉字的内码与区位码有一定的关系,所以只要通过汉字的内码就可得到该汉字的区位码,也就得到了该汉字的字模。

  查找一个汉字字模数据的算法为:

  汉字内码
-> 区位码 -> 记录号 ->
字模数据

  一个16点阵汉字其字模数据共有32字节,可以看作是一条记录,在程序中可以用一个数组存放。在DOS的图形模式下,汉字是通过描点的方法逐点画上去的。读取字模中每个字节的每一位,就能确定汉字中的每个点。故一个16×16点阵的汉字必须要32个字节的字模数据才能确定。

  以下是DOS的图形模式下显示一个16×16点阵汉字时的描点顺序图。每两个字节的字模数据确定一行。

  四、VB6中实现汉字字模转换的技巧

  在许多工程控制的应用环境中,经常需要对标准的汉字字模进行调整和转换。

  要对汉字字模进行转换首先应该正确地读出16点阵汉字在字库中的32字节的字模数据。设某一汉字的内码为ddff,其中dd表示区内码,ff表示位内码,则dd-&Ha1为该汉字的区码,ff-&Ha1为该汉字的位码。则该汉字在字库中的位置为:

  Location
= [(dd-&Ha1)×Array4 +
(ff-&Ha1)]×32

  需要注意的是,以何种方式从字库文件中读取这32字节也是一个关键问题。由于二进制(Binary)方式访问文件可以直接查看文件中指定的字节,而且二进制方式也是唯一支持用户到文件的任何位置读写任意长度数据的方法。因而以二进制方式打开汉字字库文件是最适合的。

  VB6虽然提供了较强的位运算功能,但是对于在字模转换中使用较多的移位操作,却没有提供对应的移位运算符、指令或函数。其实通过and(与)、or(或)二个位运算符即可编制一个自定义子函数来实现移位运算。

  下面的自定义子函数就是实现循环右移的:

  Public
Function byteRight(byte1 As Byte, n As Integer) As Byte ’将byte1右移n位

  Dim
TemVar As Byte ’临时变量

  Dim TemVar1 As Byte ’临时变量

  Dim X, Y As
Integer

  TemVar = byte1

  For X = 1 To n ’移多少位就循环多少次

  For
Y = 1 To 8 ’从第一位(右边第一位)开始循环右移

  Select Case Y

  Case 1

  If
(TemVar And &H1) = &H1 Then ’如果临时变量TemVar的第一位是1,

  TemVar1 =
&H1 ’则将临时变量TemVar1置1,

  Else

  TemVar1 = &H0
’则将临时变量TemVar1置0,

  End If

  Case 2

  If (TemVar And
&H2) = &H2 Then ’如果临时变量TemVar的第二位是1,

  TemVar = TemVar Or &H1
’则将其第一位置1(其它位不变),

  Else

  TemVar = TemVar And &HFE
’反之将第一位置0(其它位不变)

  End If

  Case 3

  If (TemVar And
&H4) = &H4 Then ’操作与上面相同

  TemVar = TemVar Or
&H2

  Else

  TemVar = TemVar And &HFD

  End
If

  Case 4

  If (TemVar And &H8) = &H8
Then

  TemVar = TemVar Or &H4

  Else

  TemVar = TemVar
And &HFB

  End If

  Case 5

  If (TemVar And &H10) =
&H10 Then

  TemVar = TemVar Or &H8

  Else

  TemVar
= TemVar And &HF7

  End If

  Case 6

  If (TemVar And
&H20) = &H20 Then

  TemVar = TemVar Or
&H10

  Else

  TemVar = TemVar And &HEF

  End
If

  Case 7

  If (TemVar And &H40) = &H40
Then

  TemVar = TemVar Or &H20

  Else

  TemVar = TemVar
And &HDF

  End If

  Case 8

  If (TemVar And &H80) =
&H80 Then

  TemVar = TemVar Or &H40

  Else

  TemVar
= TemVar And &HBF

  End If

  If TemVar1 = &H1 Then
’移完第八位后,如果TemVar1是1(即第一位是1)

  TemVar = TemVar Or &H80
’则将TemVar的第八位置1

  Else

  TemVar = TemVar And &H7F
’反之置0

  End If

  End Select

  Next Y

  Next
X

  byteRight = TemVar ’将TemVar的值返回给函数名

  End
Function

  尤其需要注意的是当把二进制数据写入文件中时,必须使用Byte数据类型的数组变量,而不是 String 变量。 String
被认为包含的是字符,而二进制型数据可能无法正确地存在 String
变量中。

  五、一个实际应用案例

  图形点阵液晶在现代单片机系统中是一种十分常用的显示设备,BP机、手机上的显示屏就是图形点阵液晶。它能显示汉字和图形,与行列式键盘组成了单片机系统中最常用的人机交互界面。但是直接从中文系统汉字字库中提取的汉字字模并不能直接在液晶上显示,通常都必须经过格式上的调整和转换。

  1、图形点阵液晶的汉字字模

  与在西文DOS中显示汉字不同的是,图形点阵液晶并不是简单地用画点的方式来描出汉字。以常用的HD61202图形点阵液晶显示控制模块为例,它能控制
64×64点阵液晶的显示,其显示RAM共64行,分8页,每页8行,每一页的数据寄存器分别对应液晶屏幕上的8行点,对显示RAM的一个字节单位赋值就是对当前列的8行(一页)的像素点是否显示进行控制。连续16列和相邻的2页的32字节显示RAM就可以控制一个汉字的显示区域。对这些显示RAM赋以相应的值就可以显示出一个汉字。

  HD61202图形点阵液晶显示控制模块的汉字字模的排列实际上是标准汉字字模排列形式旋转而成的。对标准汉字字模转换的目的就是在单片机系统的数据存储器中(如E2PROM)存储经过调整的连续32字节的16进制数。

  2、实际源程序

  以下这段程序是放置在汉字源文本输入框(SrcTxt)的Change事件中。通过判断输入在文本框内的字符的ASCII码是否小于零,就能判断输入的字符是不是汉字。这段程序还能计算汉字字符串的长度。同时把输入的汉字存储在一个临时文件TempSrc.txt中。由于这段代码是放在文本框的
Change事件中,它能立即更新汉字个数的显示。

  Private Sub SrcTxt_Change( )

  Static
SStr As String

  Dim i As Integer

  Dim TempFile, TempFileBinary
As String

  TotalNum = 0

  L = Len(SrcTxt.Text)

  For i = 1
To L

  tmpStr = StrConv(Mid$(SrcTxt.Text, i, 1), vbWide)

  If
Asc(Mid$(SrcTxt.Text, i, 1)) < 0 Then

  TotalNum = TotalNum +
1

  SStr = SrcTxt.Text

  Else

  MsgBox
"写入的不是汉字!"

  SrcTxt.Text = Left(SrcTxt.Text, Len(SrcTxt.Text) -
1)

  Exit Sub

  End If

  Next i

  LblNum.Caption =
Str$(TotalNum) + "个汉字"

  TempFile = App.Path + "\" +
"TempSrc.txt"

  ’TempFileBinary = App.Path + "\" +
"TempSrcBinary.txt"

  Open TempFile For Output As #1

  Print #1,
SrcTxt.Text

  Close #1

  End Sub

  在实例中选用了UCDOS
5.0汉字系统中的16点阵字库Hzk16作为提取汉字字模的标准字库。

  Private Sub CmdCnt_Click(
)

  Dim TempSrcFile As String

  Dim TempDestFile As
String

  Dim TempFile As String

  Dim HzFile As
String

  Dim To61202(32) As Integer

  Dim p(1 To 2) As
Byte

  Dim C1, C2

  Dim rec As Integer

  Dim Location As
Long ’汉字在字库中的位置

  Dim Hz(0 To 31) As Byte ’转换完的32字节的字模数据

  Dim
Buf1(0 To 31) As Byte ’暂存转换过程中的32字节字模数据

  Dim HzAll( ) As Byte
’存放全部字模数据的动态数组

  Dim LoopAll As Integer

  Dim bit, k2, k3 As
Byte

  Dim i, j, i1, k, k1, k4, k5, k6 As Integer

  DestTxt.Text =
"" ’DestTxt是目标文本框,存放转换后的16进制数据

  Flag = 0

  TempDestFile$ =
App.Path + "\" + "TempDest.txt"

  If FileExists(TempDestFile$) Then Kill
TempDestFile ’FileExists是一个检查文件是否存在的自定义函数

  If SrcTxt.Text = "" Then
’汉字输入框内无汉字则退出

  MsgBox "没有可以转换的字模源文件!"

  Exit Sub

  End
If

  HzNum = Len(SrcTxt.Text) ’获得汉字的个数

  ReDim HzAll(0 To HzNum *
32 - 1) ’重新定义动态数组的上界

  Open TempFile For Output As #1

  Print #1,
SrcTxt.Text

  Close #1

  For LoopAll = 0 To HzNum -
1

  Open TempFile For Binary Access Read As #1 ’按二进制方式打开

  Get #1,
2 * LoopAll + 1, p

  Close #1

  C1 = CStr(p(1)) - &Ha1
’区内码

  C2 = CStr(p(2)) - &Ha1 ’位内码

  rec = C1 * Array4 +
C2

  Location = CLng(rec) * 32 + 1
’该汉字在16*16点阵字库中字模第一个字节的位置

  HzFile = App.Path + "\" +
"hzk16"

  Open HzFile For Binary Access Read As #1
’读取该汉字在16点阵字库中的原始字模

  Get #1, Location, Hz

  Close
#1

  ’以下是将UCDOS字库的存储格式调整为HD61202的规范格式

  For j = 0 To 3

  If
j = 0 Then k4 = 14

  If j = 1 Then k4 = 15

  If j = 2 Then k4 =
30

  If j = 3 Then k4 = 31

  For k = 0 To 7

  bit =
&H80

  bit = byteRight((bit), (k))

  For i = 0 To
7

  k2 = byteleft(Buf1(j * 8 + k), 1) ’整个流程是由低位向高位移动,最后凑成一个字节

  k3
= byteRight((Hz(k4 - i * 2) And bit), 7 - k) ’将字节中的某位移到最低位

  k3 = k3 And
&H1 ’屏蔽掉其余7位

  Buf1(j * 8 + k) = k2 Or k3

  Next
i

  Next k

  Next j

  For i1 = 0 To 31
’将调整后的汉字字模再装入原数组

  Hz(i1) = Buf1(i1)

  HzAll(LoopAll * 32 + i1) =
Buf1(i1)

  Next

  Next LoopAll

  Open TempDestFile For
Binary Access Write As #1 ’转换结果保存到TempDestFile中

  Put #1, 1,
HzAll

  Close #1

  MsgBox "OK!"

  End
Sub

  以上程序均在中文VB6专业版上调试通过。

  以上程序在实用中取得了很好的效果。此汉字字模转换程序丰富了单片机系统开发工具的功能,是包含液晶显示功能的单片机系统在系统调试和开发过程中不可或缺的功能模块。

VB6单片机编程中的汉字处理的更多相关文章

  1. 关于keil单片机编程中的data,idata,xdata,pdata,code数据类型

    从数据存储类型来说,8051系列有片内.片外程序存储器,片内.片外数据存储器,片内程序存储器还分直接寻址区和间接寻址类型,分别对应code.data.xdata.idata以及根据51系列特点而设定的 ...

  2. 有限状态机在单片机和 Arduino 编程中的应用

    有限状态机在单片机和 Arduino 编程中的应用,个人认为在实际中这是一种思想,意味着解决一类问题. 本帖最后由 张飞 于 2015-3-4 20:18 编辑 在单片机编程中,如果在不使用操作系统的 ...

  3. 深入剖析Java编程中的中文问题及建议最优解决方法

    摘录自:http://fafeng.blogbus.com/logs/3062998.html http://www.blogbus.com/fafeng-logs/3063006.html 深入剖析 ...

  4. js replace 全局替换 以表单的方式提交参数 判断是否为ie浏览器 将jquery.qqFace.js表情转换成微信的字符码 手机端省市区联动 新字体引用本地运行可以获得,放到服务器上报404 C#提取html中的汉字 MVC几种找不到资源的解决方式 使用Windows服务定时去执行一个方法的三种方式

    js replace 全局替换   js 的replace 默认替换只替换第一个匹配的字符,如果字符串有超过两个以上的对应字符就无法进行替换,这时候就要进行一点操作,进行全部替换. <scrip ...

  5. 在KEIL下查看单片机编程内存使用情况

    原文链接:https://blog.csdn.net/D_azzle/article/details/83410141 截至到目前为止,本人接触单片机也有将近一年的时间.这一年以来也接触过了很具代表性 ...

  6. 为什么C语言是最适合单片机编程的高级语言!

    为什么还在用C语言编程?答案是:C语言是最适合单片机编程的高级语言. 这个问题的意思应该是:现在有很多很好用的高级语言,如java,python等等,为什么这些语言不能用来编写单片机程序呢?那么这个问 ...

  7. [zz]如何在C语言程序中处理汉字

    学习过C语言的人也许有时会遇到这样一个问题:如何用变量存储汉字以及对这些变量进行操作.目前许多C语言参考书中都没涉及到这个问题,程序中多为处理英文变量和英文字符串,涉及到汉字的情况也大都是在print ...

  8. 你不知道的this—JS异步编程中的this

    Javascript小学生都知道了javascript中的函数调用时会 隐性的接收两个附加的参数:this和arguments.参数this在javascript编程中占据中非常重要的地位,它的值取决 ...

  9. Java EE 编程中路径

    版权声明:未经博主允许,不得转载 首先我们要限定一个范围,是一个项目,或是以个访问地址..就先以一个项目为限定的范围 前述: 学过物理学的都知道相对运动和绝对运动, 虽然是相似的概念,但这里的要简单得 ...

随机推荐

  1. Unity3D 4.x怎样实现动画的Ping Pong效果

    近期在看Unity官方的Stealth项目教学视频,视频使用的是Unity旧的版本号,而我如今正在使用的是Unity 4.5,动画系统的操作全然不同了. 依照视频的方式根本无法设置动画的Ping Pi ...

  2. Java 发展历史

    Java自1995诞生,至今已经20多年的历史. Java的名字的来源:Java是印度尼西亚爪哇岛的英文名称,因盛产咖啡而闻名.Java语言中的许多库类名称,多与咖啡有关,如JavaBeans(咖啡豆 ...

  3. Linux C程序操作Mysql 调用PHP采集淘宝商品 (转)

    还是继续这个项目. 在上一篇Linux下利用Shell使PHP并发采集淘宝产品中,采用shell将对PHP的调用推到后台执行,模拟多线程. 此方法有一致命缺点,只能人工预判每个程序执行时间.如果判断时 ...

  4. sqlserver 同义名的使用

    USE [ccflow5]GOdrop synonym ccusergo/****** Object:  Synonym [dbo].[ccuser]    Script Date: 11/12/20 ...

  5. 如何用Photoshop画一个发光金币(unity游戏素材教程)

    做好的发光金币预览图: 以下为如何用Photoshop画一个发光金币教程: [1]如上图1-2,新建,名称改为Coin,宽度20像素,高度20像素,分辨率72,背景白色: [2]使用Alt+Shift ...

  6. iText使用经历

    最近用iText搞了下PDF,虽然一路趟坑而过,毕竟是搞出来了,所以iText还是不错的开源PDF生成软件的.先看搞出来的PDF长啥样: 然后看一路趟过来的坑: 1.表格怎么生成,具体是行怎么生成?列 ...

  7. css 填坑常用代码分享[居家实用型]

    原文地址 http://www.cnblogs.com/jikey/p/4233003.html 以下是常用的代码收集,没有任何技术含量,只是填坑的积累.转载请注明出处,谢谢. 一. css 2.x ...

  8. linux下的pd

    东西叫OpenSystemArchitect 地址在http://www.codebydesign.com/SystemArchitect 运行之前,先sudo apt-get install lib ...

  9. BASIC-21_蓝桥杯_Sine之舞

    思路: 先根据例子找出规律,列出递归要打印的数据; 示例代码: #include <stdio.h> int n = 0; void dg(int x){ int i = 0; if (x ...

  10. phpexcel导入数据出现PHPExcel_RichText Object解决办法

    在导入excel的时候会出现异常情况,有的问题出现PHPExcel_RichText object,错误代码如下 PHPExcel_RichText Object ( [_richTextElemen ...