非汉字系统下汉字的打印输出

发表于:2007-07-14来源:作者:点击数: 标签:
[摘要]介绍了在无汉字字库的打印机上,无需启动汉字操作系统打印汉字的方法,并给出了非汉字系统下打印输出含有汉字的文本文件的实用VC++源程序。 [关键词]汉字打印,Zebra系列, VC++语言,24*24点阵字库,文本文件 电脑用户中,有相当一部分用户的打印机不带汉字
[摘要]介绍了在无汉字字库的打印机上,无需启动汉字操作系统打印汉字的方法,并给出了非汉字系统下打印输出含有汉字的文本文件的实用VC++源程序。 [关键词]汉字打印,Zebra系列, VC++语言,24*24点阵字库,文本文件

  电脑用户中,有相当一部分用户的打印机不带汉字库,他们打印输出汉字的一般方法是,首先启动汉字操作系统,使汉字打印驱动程序驻留内存,再把含有汉字的文本文件送打印机输出,或特定格式的汉字文件经应用程序打印输出;这对于只是单一打印汉字文件,还是比较简单实用的,但有时在我们自编的应用程序中,只是要打印汉字,而不需要屏幕显示或键盘输入汉字,在汉字系统下运行应用程序时,会带来一些副作用,如汉字系统占用内存资源、使显示速度变慢等。若在西文状态下,使不带汉字库的打印机也能打印输出汉字,即可避免因启动汉字系统运行应用程序而带来的麻烦。

  笔者针对上述问题,经过分析研究Zebra打印机命令码,通过VC++语言编程,用矩阵转置的方法实现了西文状态下汉字的打印。

一、非汉字系统下汉字打印实现原理

  以目前拥有工业用户较多的Zebra系列打印机为例,说明汉字打印实现原理,汉字打印的字摸数据来源于UCDOS的24*24点阵字库。

  打印机为用户提供了自定义字符功能,标准字符存在打印机的ROM中,而用户自定义字符则存在打印机的RAM中或直接对内存进行操作。同时为了避免因文本文件中出现重复汉字或图形符号造成频繁读取字库而影响文本输出速度,我们直接对内存进行操作。对图像而言,由于占用内存较大,影响运行速度,所以放在RAM中。

  把汉字库字模点阵数据作为自定义字符的数据,在打印机的内存中生成自定义字符,再输出内存中的自定义字符,即可在打印机上打印汉字。

  打印机自定义下载字符命令为:

~DGd,t,w,data  其中~DG为设置打印机为下载图形模式;

d为储存图形的目标设备(内存地址);

t为图像总的字节数;

w为每行字节数;

data为ASSII为十六进制串图像定义。因24×24点阵打印一个字需要24×3=72个字节,所以在这里 t=72,w=3。

  选择打印字符集命令为:

^XGd,t,w  其中^XG 为打印字符集命令;

d为储存图形的目标设备(内存地址);

t为图像总的字节数;

w为每行字节数。

  由于24*24点阵打印字库字模数据的存贮序列是按列优先的顺序,每列的24点用连续的3个字节存储,其顺序是按字模的上中下排列,且每个字节的最高位在上、最低位在下;而Zebra系列打印机打印输出序列是按行优先的顺序打印的,因此字模数据的存贮序列矩阵需行列转置变换后才可送打印机打印。

二、汉字文本文件的打印

  利用上述原理,可以在自己应用程序中,实现在非汉字系统下,不带汉字库的打印机上(或带汉字库的打印机设置为英文方式)输出汉字。

  作为应用,用VC++语言编制一打印含有汉字的文本文件的程序。

编程思路如下:置打印机为信函打印质量方式及每英寸10个字符,以使输出一个汉字和图形符号占两个字符位置,处理文本文件中的字串,当字串中遇到汉字时(连续两个字符的第一个字符 ASCII 码大于 175 且第二个字符ASCII码大于 160),读取UCDOS的24*24点阵汉字库HZK24S(宋体)或HZK24F(仿宋体) 或 HZK24K(楷体)或HZK24H(黑体)中该汉字对应的点阵数据,当字串中遇到图形符号时(连续两个字符ASCII码的第一个字符ASCII 码大于 160 小于176且第二个字符ASCII码大于 160),读取UCDOS的 24* 24 点阵图形符号库HZK24T中该图形符号对应的点阵数据,用文本方式或图形方式输出该汉字或图形符号,否则输出原字符。

根据以上理解,得出如下读取汉字字模的算法:

如前面所述,汉字以字模的形式储存于字库中,每个汉字在字库中有唯一的区位码与之对应,根据某一汉字的机内码可以确定其区位码及其在字库中的起始位置,就可以从字库中取出汉字字模。具体步骤如下:

(1)根据机内码计算汉字的区位码

区码=机内码高字节-A1H

位码=机内码底字节-A1H

(2)根据区位码计算汉字在字库中的偏移量

汉字在字库中的偏移量L=((区码-m)*94+位码)*n 其中,m位汉字在字库中的起始号,n为每个汉字所占的字节数。字库中:偏移量=((区码-m)*94+位码)*(字库的点阵数^2/8) /*因为一个汉字的每一个点是作为一个位 (bit)处理的,又8位为一个字节*/

三、打印汉字文本文件VC++源程序

  打印含有汉字的文本文件源程序的主要函数源代码如下所示:

//**********************************************
//功能    : 将要打印的部分汉字字库装入打印机内存中
//输入参数: sHz 当前需要初始化的汉字字串
//输出参数: HZtobyte 汉字点阵字节流                       
//**********************************************
#define FONTK_NAME "c:\\Cclib\\hzk24k"//标准24点阵楷体汉字字库
#define FONTT_NAME "c:\\Cclib\\hzk24t"//标准24点阵汉字索引库
void CHesnprinterDlg::MakeHZHEX(CString &sHZ,CString &HZtobyte)
{
CFile theFile,theFile_t;
CString  csFileName=FONTK_NAME,csFileName_t=FONTT_NAME;
BOOL bOpenOK,bOpenOK_t;
HZtobyte="";   
// Open the file without the Create flag
bOpenOK = theFile.Open( csFileName,
                    CFile::modeRead  );
bOpenOK_t=theFile_t.Open( csFileName_t,
                    CFile::modeRead  );
if ((bOpenOK==0)||(bOpenOK_t==0))
{
CString Msg="字库文件不能打开!";
AfxMessageBox(Msg,MB_OK|MB_ICONINFORMATION);
}
theFile.Seek( 0, CFile::begin );
theFile_t.Seek( 0, CFile::begin );
//
CString lbs,hbs,sp;
BOOL HzFlag;
long noffset;
int i,j,hb,lb,k,offset=0;
BYTE bytes[72];
HzFlag=FALSE;
int hh=sHZ.GetLength();
for(i=0;i175)
{
hb=hb-0xb0;// 汉字:hb=hb-0xb0;
lb=lb-0xa1;
noffset=hb*94*72+lb*72;
theFile.Seek( noffset, CFile::begin );
theFile.Read(bytes,72);
}
else if((hb>160)&&(hb<176))
{
hb=hb-0xa1;// 图形字符:hb=hb-0xa1
lb=lb-0xa1;
noffset=hb*94*72+lb*72;
theFile_t.Seek( noffset, CFile::begin );
theFile_t.Read(bytes,72);
}
//点阵字库转置
Exchange(bytes);
//取得汉字的的点阵某位为空,即无化点,则置为0
CString HZtobyte_temp;
for(j=0;j<72;)
{
sp.Format("%02x%02x%02x",(unsigned int)bytes[j]
,(unsigned int )bytes[j+1],(unsigned int)bytes[j+2]);

for(k=0;k0xa0 )
{
HzFlag=TRUE;
continue;
}
else
{
sp1.Format("^FO%d,%d^A0%d,%d^FD%c^FS"
,xx,yy,Font_W,Font_H,signStr.GetAt(i));
sp+=sp1;
xx+=Font_W;
continue;
}
}
}
Command=sp;
}
//**********************************************
//功能    : 点阵字库转置
//变换参数: pch 列优先级字库点阵->行优先级字库点阵                   
//**********************************************
void CHesnprinterDlg::Exchange(BYTE * pch)
{
CString str,str_temp;
BYTE iMatrix[72][72];
int i,j;
for(i=0;i<72;i++)
{
str_temp=Byte2Bin(pch[i]);
str+=str_temp;
}
for(i=0;i<24;i++)
for(j=0;j<24;j++)
{
str_temp=str.GetAt(i*24+j);
sscanf(str_temp,"%d",&iMatrix[i][j]);
}
for(i=0;i<24;i++)
for(j=0;j=0;i--)
{
str1.Format("%d",(bt>>i)&1);
str2+=str1;
}
return str2;
}
//位转换成字节运算
BYTE CHesnprinterDlg::Bin2Byte(CString str)
{
int iBit,iSum=0;
for(int i=7;i>=0;i--)
{
iBit=str.GetAt(7-i)-'0';
iSum+=iBit*(1<
以上是该程序的部分汉字处理函数,只要设置好PC机和打印机器之间的串行通信协议,就可以直接
处理汉字与字母混合的字符串了。
运行本程序需要当前目录中有UCDOS的24*24点阵打印字库 ( 图形符号库HZK24T和宋体字库HZK24S、
仿宋体字库HZK24F、楷体字库HZK24S、黑体字库HZK24S其中之一)。程序在586微机、Zebra系列 96XiIII打印机
及WIN98环境下运行通过。
参考文献
[1] 任铁良,高级语言直接在打印机上绘图,《现代计算机》,1995年第8期
[2] Zebra工业用条形码打印机操作手册和编程手册。

原文转自:http://www.ltesting.net