ucGUI汉字处理技巧

ucGUI版本3.94以上应用支持双字节的处理了,比如中文,日文等。基本上汉字的处理都可以了.不管是显示,修改,输入法.

1:汉字字库

要实现汉字双字节的显示,只要用其相应的工具把一个字库转换成点阵就好了。指定控件相应的字体就能显示了,但还有一个问题,虽然能正常显示了,当用汉字输入到EDIT等控件时,移动光标,可以看到移动是的半个汉字,这样就出问题了,出现这样的问题就是计算字符个数时出错了。


2:调用GUI_UC_SetEncodeGBK()
在程序开始时调用 GUI_UC_SetEncodeGBK()这个过程就可以了,实际上就是初始化 GUI_Context.pUC_API的一个指针,这个包含了计算字符的宽度,大小等过程。
如下的代码:
static const GUI_UC_ENC_APILIST _API_Table_GBK = {
  _GetCharCode,     /*  return character code as U16 (Unicode) */
  _GetCharSize,     /*  return size of character: 1/2/3        */
  _CalcSizeOfChar,  /*  return size of character: 1/2/3        */
  _Encode           /*  Encode character into 1/2/3 bytes      */
};
void GUI_UC_SetEncodeGBK(void) {
  GUI_LOCK();
  GUI_Context.pUC_API = &_API_Table_GBK;
  GUI_UNLOCK();
3:一个BUG处理
如上处理后,EDIT等控件能正常显示和修改修入汉字了。
但在我使用的过程中发现了一个BUG,几次修改EDIT控件的值(包括汉字时),在字符结尾处就出现了乱码。正常的字符都显示出来了。
通过跟踪发现,需要对一个方法更改:
/*********************************************************************
*
*      GUICharLine.c  GUI_GetLineDistX
*
*  This routine is used to calculate the length of a line in pixels.
*/
int GUI__GetLineDistX(const char GUI_UNI_PTR *s, int MaxNumChars) {
  int Dist = 0;
  if (s) {
    U16 Char;
    #if GUI_COMPILER_SUPPORTS_FP
      if (GUI_Context.pAFont->pafEncode) {
        return GUI_Context.pAFont->pafEncode->pfGetLineDistX(s, MaxNumChars);
      }
    #endif
    while (--MaxNumChars >= 0) {
Char  = GUI_UC__GetCharCodeInc(&s);
      if(Char == 0)        //jhting: 2012-09-26 Edit_ display GBK BUG 
  break;
      Dist += GUI_GetCharDistX(Char);
    }
  }
  return Dist;

}


Ucgui汉字库的建立方法

1.  ucgui包括两种字体:①等宽字体:所有字体中的字都是相同的宽度,不能对哪一个字体单独设置一种宽度,在ucgui中的结构体是GUI_FONT_MONO;②均衡字体:字体中的字都有独立的宽度,字体中的每一个字都有一个单独的宽度,可以为每个字单独设定字体,它在UCGUI上的结构体是GUI_FONT_PROC;
2.   ucgui中的等宽字体都是存储在一个数组中,由于每一个字体中的字都是相同的宽度,因此都存储在同一个数组中;但是对于均衡字体来说,由于字体中的每一个都是不同的字体因此每一个字单独存储在一个数组中,然后将每一个字符的宽高及字的点阵存为一个数组即字符信息,ucgui中字符信息的结构体是GUI_CHARINFO,所有的字符信息再存储在一个数组之中,成为字符集,包含每一个字符的信息(宽高及点阵);
3.   在等宽字体中,不仅所有的字符宽度相同,高度也是相同的,但是对于均衡字体来说,宽高都是可以不同的;
4.   在UCGUI中每种字体含的字符集不同,ucgui中有一节专门对ucgui的字体作了介绍;
5.   程序中直接输入汉字的实现,即在编程中将要显示在LCD的汉字直接在程序中写出。在UCGUI中介绍的用unicode编码进行输入的方法相当的繁琐,当需要输出入的汉字量非常大的时候,这个问题就更加的突出。经过分析ucgui的内核知道,程序中输入的unicode码其实就是字库中GUI_FONT_PROP定义的该字映像地址,在程序中直接输入字母后计算机获得的是汉字内码,所以只要将GUI_FONT_PROP中的映像地址改为字母的内码就行了,对于英文字母就是ASCII编码,而汉字就是汉字内码,下面简单介绍常用的16点阵汉字的编码:
在UC/GUI中F16_1hk.c文件中定义的GUI_FONT_PROP结构体对象,通过注释了解映像地址和字模数据存储地址的对应的关系。
GUI_FLASH  constGUI_FONT_PROP  GUI_Font16_1HK_Prop1= {
              0x3041, 
              0x3093, 
              &GUI_Font16HK_CharInfo\[\0], 
              (void GUI_FLASH*)&GUI_Font16_1HK_Prop2   
};
6.    建立汉字字库
在UC/GUI中动态地读取字模是无法实现的,即当程序运行时动态地从汉字库中读取所需要的字母的字模,因此只有把所有一级常用汉字的字模全部取出,按照UC/GUI中字库创建的标准去创建新的字库就可以了。下面以在F16_HZ_LEI.C中创建字体GUI_Font6_HZ为例来说明具体的步骤。
第一:声明全局字体结构体对象GUI_Font16_HZ,该声明必须在GUI.H文件中加以说明,
extern const GUI_FONTGUI_Font16_HZ ;
第二:定义一个用于存放字模数据的数组。
GUI_FLASH const unsigned char acFont16HZSong_16_0001 =[……]   (当然这样的定义就是我们之前所说的均衡字体的定义,每一个字符的点阵存于一个数组中)
第三:定义一个GUI_CHARINFO的结构体对象数组,用于说明每个字母的字模数据在程序段存储的方式。
GUI_FLASH const GUI_CHARINFO GUI_Font16_HZ_CharInfo/[3760\]= {{16,16,2,(voidGUI_FLASH*)&acFont16HZ\[\0],……,16,16,2,(voidGUI_FLASH*)&acFont16HZ\[3759\]},} ;
第四:按汉字内码的高位来定义多个结构体GUI_FONT_Prop0={0xb0a1,0xb0fe,&GUI_Font_HZ_CharInfo\[0\],(voidGUI_FLASH*)&GUI_Font_HZ_Prop1};
第五:把创建的汉字库文件F16_HZ_LEI.C添加到UC/GUI的工程中,通过以下语句实现在LCD上显示汉字:GUI_SetFont(&GUI_Font16_HZ); GUI_DispStringAt(GUI_UC_START “西安邮电学院” GUI_UC_END,11,11);
7.   通常情况下我们所使用的开发板的存储器都较小,并且我们在一篇文章中不可能使用所有的十六点阵或者十二点阵包含的所有汉字,那么此时我们就需要从这些点阵中挑选出我们需要使用的汉字。这种情况下汉字的机内码存储就不是连续的,有些时候下可能得为单独的一个汉字建立一个GUI_FONT_PROP结构,然后再将它们链成链表,这样做就可以直接使用以下两种方法:
比如我们此刻要在LCD上显示“世界你好”:
方法一、const unsigned charhelloworld[] = "世界你好";
      GUI_DispString((constchar*)helloworld);
此时是编译器将汉字转换为机内码
方法二、
const unsigned charhelloworld[]={0xca, 0xc0, 0xbd, 0xe7, 0xc4, 0xe3, 0xba, 0xc3,0x00};  
        GUI_DispString((const char*)helloworld);
此时编译器利用数组中存储的汉字的机内码找到相应的汉字输出至LCD上。
 
如上两种比较, 结果是一样的,唯一不同的是, 第一种方法显示汉字时, 无须使用知道汉字的机内码, 而是由编译器来转换的,但我要说的是, 其实两者本质是一样的, 只是对使用者来说有表面上的不同.比较以上的两种显示汉字时构造字符串的方法,我们可以得到一个启示, 对于第二种, 我们可以采取自定义汉字机内码, 然后直接通过自定义机内码来显示汉字,这一点我已经在"建立自定义小型汉字库说明"一文当中说明了,现在我想说的是对于采用第一种方法显示汉字的建立自定义小型字库的方法。

#include "GUI.H"
#ifndef GUI_FLASH
#define GUI_FLASH
#endif
extern GUI_FLASH const GUI_FONT GUI_FontHZ12;
//世
GUI_FLASH const unsigned char acFontHZ12_cac0[24] = {
0x04,0x40, 0x24,0x40, 0x24,0x40, 0x24,0x40, 0xff,0xf0, 0x24,0x40,0x24,0x40, 0x24,0x40,
0x27,0xc0, 0x24,0x40, 0x20,0x00, 0x3f,0xf0
};
//界
GUI_FLASH const unsigned char acFontHZ12_bde7[24] = {
0x3f,0xc0, 0x24,0x40, 0x3f,0xc0, 0x24,0x40, 0x3f,0xc0, 0x04,0x00,0x0b,0x00, 0x38,0xf0,
0xc9,0x20, 0x09,0x00, 0x11,0x00, 0x61,0x00
};
//你
GUI_FLASH const unsigned char acFontHZ12_c4e3[24] = {
0x12,0x00, 0x12,0x00, 0x27,0xf0, 0x24,0x20, 0x69,0x40, 0xa1,0x00,0x25,0x40,
0x25,0x20, 0x29,0x10, 0x31,0x10, 0x25,0x00, 0x22,0x00
};
//
//好
GUI_FLASH const unsigned char acFontHZ12_bac3[24] = {
0x20,0x00, 0x27,0xe0, 0x20,0x40, 0xf8,0x80, 0x48,0x80, 0x48,0xa0,0x57,0xf0, 0x50,0x80,
0x30,0x80, 0x28,0x80, 0x4a,0x80, 0x81,0x00
};
GUI_FLASH const GUI_CHARINFO GUI_FontHZ12_CharInfo[4] = {
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_cac0},
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_bde7},
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_c4e3},
{ 12, 12, 2, (void GUI_FLASH *)&acFontHZ12_bac3}
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa4= {
0xbac3,
0xbac4,
&GUI_FontHZ12_CharInfo[3],
0
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa3= {
0xc4e3,
0xc4e4,
&GUI_FontHZ12_CharInfo[2],
(void *)&GUI_FontHZ12_Propa4
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa2= {
0xbde7,
0xbde8,
&GUI_FontHZ12_CharInfo[1],
(void *)&GUI_FontHZ12_Propa3
};
GUI_FLASH const GUI_FONT_PROP GUI_FontHZ12_Propa1= {
0xcac0,                       //在GUI_CHARINFO结构中定义的数组中的对应起始地址cac0 
0xcac1,                       //在GUI_CHARINFO结构中定义的数组中的对应结束地址
&GUI_FontHZ12_CharInfo[0],      //在GUI_CHARINFO结构中定义的数组的位置从0开始
(void*)&GUI_FontHZ12_Propa2     //下一数组的索引地址
};


GUI_FLASH const GUI_FONT GUI_FontHZ12 = {
GUI_FONTTYPE_PROP_SJIS,
12,
12,
1,
1,
(void GUI_FLASH *)&GUI_FontHZ12_Propa1  //下一数组的索引地址


};



转载于:https://www.cnblogs.com/markmin214/archive/2013/03/30/2994729.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值