|
|
楼主 |
发表于 2007-3-5 13:05:50
|
显示全部楼层
还有这个
英文DOS下,不带汉字库实现中文界面的方法:
1、列出界面上需要的所有字符串。
2、利用下面的GetZMToFile()程序段,将这些需要使用的字符串对应的字模全部转存到不同的C语言源文件中。
3、将第二步生成的C源文件中的代码复制到一个公共头文件中(头文件示例),这样就有了一个专用的字模库,将跟随程序一起编译,即免去汉字库。
4、有了ASCII字模头文件,就可以编写相应的汉字显示程序了,详见我写的一套从专用ASCII字模头文件显示汉字的程序。
附:程序段1----GetZMToFile();
功能:可以将指定字符串的字模读出,转存到一个C语言源码文件,以生成专用字模库。
///////////////////////////////////////////////////////////////////////
int GetZMToFile(int h,int w,int type,char *arrayname,unsigned char *HZPTR,
char *filename)
//w汉字的宽度;h汉字的高度;type字型号(字体,1仿宋,2黑,3楷,4宋);
//space字间距;isHorizontal竖向显示标致;xPosition 列坐标位置;yPosition 行坐标位置;
//HZPTR为所要显示的字符串;color汉字的颜色;
{
int HZKFILE; //汉字库文件句柄;
FILE *zmfile;
int HZSIZE;//,old_w; //字模数组长度;
unsigned char HZKMAT[801];//存放字模的数组,假设可能出现的最大汉字是80X80;
unsigned char WriteMat[801];
char hzkname[80]; //暂存库名的数组;
char ch[8]; //临时数组,用于整型数到字符型数的转换;
unsigned char qh,wh; //汉字的区号和位号;
unsigned long offset; //字库文件内部指针的定位标致;
unsigned char c_qh,c_wh; //暂存x坐标的变量;
//unsigned char mask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
register int i,k,x0,y0,pos; //只用于计数的变量;
char test[80];
unsigned char zm[16][2][8];
char c_ch[5];
int arr_a,arr_b;
unsigned char *p;
int n = 0 ;
arr_a = 0 ;
p = HZPTR;
while(*p!='\0')
{
if(*p & 0x80)
p++;
arr_a ++ ;
p ++ ;
}
memset(HZKMAT,0,801); //将数组HZKMAT中的所有元素清零;
// old_w=w; //将原始的 w 记下来,因为 w 的宽度不一定是汉字的宽度用于字间距;
memset(hzkname,0,80);//将 hzkname 中的所有元素清零,为稳定性而加,可不要;
strcpy(hzkname,"..\\hzk\\zk");// \
strcat(hzkname,itoa(h,ch,10));// |
strcat(hzkname,"x");// >--形成字库文件名;
strcat(hzkname,itoa(w,ch,10));// |
strcat(hzkname,itoa(type,ch,10));// /
if((HZKFILE=open(hzkname,O_RDONLY|O_BINARY))==-1) //共享方式打开汉字库;
{ //如果打不开汉字库则将最相似大小的字库打开并从中读取字模;
Clrscr(0,0,getmaxx(),getmaxy(),0); //清除全屏;
closegraph();
printf("\nCan not open hzk !"); //输出文件没有打开的提示信息;
getch(); //接受一个键盘输入(任意键);
exit(1); //函数返回 -1 出错标致;
}
else //如果汉字库打开了,则计算其宽度,以读取字模;
{
if((w%8)>=1)
w=(w/8)*8+8; //如果汉字的宽度模8大于等于1则算另外一个字节计算;
else //即将宽度加上一个字节;
w=w/8*8; //否则其小于1的话,将按原字节数计算;
HZSIZE=w/8*h; //计算将要读取多少位字模;
}
arr_b = HZSIZE;
//---------------------------------------------------------------------
if((zmfile = fopen( filename, "w+" ) ) == NULL)
{ //若汉字库没有打开;
closegraph();
printf("\nCan not open file : \"%s\" !",filename); //输出文件没有打开的提示信息;
getch(); //接受一个键盘输入(任意键);
exit(1); //函数返回 -1 出错标致;
}
fprintf(zmfile,"\t\n/*---------------------------------------------------------------------*/\n");
fprintf(zmfile,"\t/*%s*/\n",HZPTR);
fprintf(zmfile,"\tint %s[%d][%d] = {\n",
arrayname, arr_a, arr_b );
// fprintf(zmfile,"\tmemset(%s,'\\0',%d*%d);\n",arrayname,arr_a,arr_b);
n = 0 ;
while(*HZPTR!=NULL)
{
if((*HZPTR&128)!=0) //判断其是否为汉字;
{
//如果列坐标超出了640,不能再显示下一个汉字时,而汉字又没有显示完,
//则将列坐标重新设置为零,横坐标加上此行汉字的高度再加上4,目的是为了美观;
qh=HZPTR[0]-0xa0;// \
wh=HZPTR[1]-0xa0;// |
offset=(long)(94*(qh)+(wh))*HZSIZE;// >--- 取字模;
lseek(HZKFILE,offset,SEEK_SET);// |
read(HZKFILE,HZKMAT,HZSIZE);// /
memset(WriteMat,'\0',801);
strcpy(WriteMat,"\t{");
for(i = 1 ; i <= arr_b ; i ++)
{
if((int)HZKMAT[i-1] < 10 )
sprintf(c_ch," %d",(int)HZKMAT[i-1]);
else
if((int)HZKMAT[i-1] < 100)
sprintf(c_ch," %d",(int)HZKMAT[i-1]);
else
sprintf(c_ch,"%d",(int)HZKMAT[i-1]);
if( i!=arr_b)
{
c_ch[3] = ',' ;
c_ch[4] = '\0';
}
else
c_ch[3] = '\0';
strcat(WriteMat,c_ch);
if(i%16==0)
{
if(i!=arr_b)
strcat(WriteMat,"\n");
fprintf(zmfile,"%s",WriteMat);
memset(WriteMat,'\0',801);
if(i!=arr_b)
strcpy(WriteMat,"\t ");
}
}
{
strcat(WriteMat,"}");
if(*(HZPTR+2)!='\0')
strcat(WriteMat,",\n");
fprintf(zmfile,"%s",WriteMat);
memset(WriteMat,'\0',801);
}
n ++ ;
HZPTR+=2; //的汉字宽度,HZPTR+=2是将要显示的字符串向后移两个字;
} //节,因为汉字占用两个字节;
else //如果不是汉字;
//-------------以下是对ASCII码的显示方法及其控制--------------//
{
offset = HZPTR[0]-0x21;
if(HZPTR[0]==' ')
offset = 92*94+HZSIZE;
lseek(HZKFILE,offset*HZSIZE*1L,SEEK_SET); //移文件指针到字库文
read(HZKFILE,HZKMAT,HZSIZE); //件ASCII码开始处;
memset(WriteMat,'\0',801);
strcpy(WriteMat,"\t{");
for(i = 1 ; i <= arr_b ; i ++)
{
// if((int)HZKMAT[i-1] == ' '||(int)HZKMAT[i-1] == 0)
// strcpy(c_ch," 0");
// else
if((int)HZKMAT[i-1] < 10 )
sprintf(c_ch," %d",(int)HZKMAT[i-1]);
else
if((int)HZKMAT[i-1] < 100)
sprintf(c_ch," %d",(int)HZKMAT[i-1]);
else
sprintf(c_ch,"%d",(int)HZKMAT[i-1]);
if( i!=arr_b)
{
c_ch[3] = ',' ;
c_ch[4] = '\0';
}
else
c_ch[3] = '\0';
strcat(WriteMat,c_ch);
// if(i != 0 && i % 20 == 0 )
if(i%16==0)
{
if(i!=arr_b)
strcat(WriteMat,"\n");
fprintf(zmfile,"%s",WriteMat);
memset(WriteMat,'\0',801);
if(i!=arr_b)
strcpy(WriteMat,"\t ");
}
}
{
strcat(WriteMat,"}");
if(*(HZPTR+1)!='\0')
strcat(WriteMat,",\n");
fprintf(zmfile,"%s",WriteMat);
memset(WriteMat,'\0',801);
}
n ++ ;
HZPTR+=1; //此处的字符指针只移一位,是因为ASC字符只占一个字节;
} //(汉字占两个字节,所以加2);
}
close(HZKFILE); //关闭汉字库文件;
fprintf(zmfile,"};\n");
/* if(n<10)
fprintf(zmfile , "\tstrcpy ( %s[%2d] , \"%s\" );\n",arrayname,n,"\\0");
else
fprintf(zmfile , "\tstrcpy ( %s[%d] , \"%s\" );\n",arrayname,n,"\\0");
*/ fprintf(zmfile,"/*---------------------------------------------------------------------*/\n");
fclose(zmfile);
return(0); //返加0值表示没有出错;
}
///////////////////////////////////////////////////////////////////////
程序段2:Puthz();
功能:利用字模数组中的字模将HZPTR中指定的汉字格式化显示到屏幕上,函数
参数char *HZPTR与GetZMToFile()中的char *HZPTR必须完全相同,其中ZM参数
为GetZMToFile()生成的头文件中的arrayname的地址;具体使用方法见示例。
///////////////////////////////////////////////////////////////////////
int Puthz(int h,int w,int space,int isHorizontal,
int slantingflag,int xPosition,int yPosition,
unsigned char *HZPTR,int *ZM,int color)
//w汉字的宽度;h汉字的高度;type字型号(字体);space字间距;
//isHorizontal竖向显示标致;slantingflag汉字倾斜标致;xPosition 列坐标位置;
//yPosition 行坐标位置;HZPTR为所要显示的字符串;color汉字的颜色;
{ ///////////slantingflag为斜体标致,1和2表示斜体(2比1斜得历害),0表示正体;
int HZKFILE; //汉字库文件句柄;
// int space = 0,isHorizontal = 0 , slantingflag = 0 ;
int old_w,HZSIZE; //字模数组长度;
unsigned char HZKMAT[801]; //存放字模的数组;
unsigned char qh,wh, ch[8]; //汉字的区号和位号;
int xx; //暂存x坐标的变量;
unsigned char mask[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
int i,j,k,x0,y0,pos; //只用于计数的变量;
int n = 0 ,arr_a,arr_b;
char *p;
arr_a = 0 ;
p = HZPTR;
while(*p!='\0')
{
if(*p & 0x80)
p++;
arr_a ++ ;
p ++ ;
}
memset(HZKMAT,0,801); //将数组HZKMAT中的所有元素清零;
old_w=w; //将原始的 w 记下来,因为 w 的宽度不一定是汉字的宽度用于字间距;
{
if((w%8)>=1)
w=(w/8)*8+8; //如果汉字的宽度模8大于等于1则算另外一个字节计算;
else //即将宽度加上一个字节;
w=w/8*8; //否则其小于1的话,将按原字节数计算;
HZSIZE = w/8*h;
arr_b = HZSIZE;
}
//---------------------------------------------------------------------
xx=xPosition; //将原始的列坐标暂存;
n = 0 ;
while(*HZPTR!=NULL)
{
if((*HZPTR&128)!=0) //判断其是否为汉字;
{
if(isHorizontal==0) //判断是否为横向显示;
{
if((xPosition+w+space)>=640&&*HZPTR!=NULL)
{ //如果当前的列坐标不能显示下一个汉字则换行;
yPosition+=h+4, //以上功能用当前x坐标加上汉字的宽度w再加
xPosition=0; //上字间距space来实现;
}
}
//如果列坐标超出了640,不能再显示下一个汉字时,而汉字又没有显示完,
//则将列坐标重新设置为零,横坐标加上此行汉字的高度再加上4,目的是为了美观;
if(isHorizontal==1) yPosition+=h+space,xPosition=xx;
for( i = 0 ; i < arr_b ; i ++)
HZKMAT = (unsigned char)(*(ZM+n++));
y0=yPosition;//将汉字显示位置的行坐标暂存,以在显示下一汉字时用;
for( i=0 ; i<h ; i++ ) //从汉字的0行到汉字的高度循环;
{
x0=xPosition; //将汉字显示的列坐标暂存,以在下一条显示时使用;
pos=w/8*i; //此行中的pos用于字模数组HZKMAT中下标定位,以取字模;
for(j=0;j<w;j++) //从0到汉字的宽度循环;
{
if((mask[j%8]&HZKMAT[pos+j/8])!=NULL)//按位相与后不为0则画点;
if(slantingflag>=2)putpixel(x0+(h-i),y0,color);//断倾斜标致;
else if(slantingflag==1)putpixel(x0+(h/2-i/2),y0,color);
else putpixel(x0,y0,color); //屏幕当前坐标按颜色值画点;
x0++; //画好后将列坐标加上1;
}
y0++; //一行字模画完后将画下一行,y0++是将行数加1,到下一行;
}
xPosition+=old_w+space; //由于old_w是此函数的入口参数,是最标准;
HZPTR+=2; //的汉字宽度,HZPTR+=2是将要显示的字符串向后移两个字;
} //节,因为汉字占用两个字节;
else //如果不是汉字;
//-------------以下是对ASCII码的显示方法及其控制--------------//
{
if(isHorizontal==0) //判断是否为横向显示;
{
if((xPosition + w + space)>=640&&*HZPTR!=NULL)
{ //如果当前的列坐标不能显示下一个汉字则换行;
yPosition+=h+4;
xPosition=0; //以上功能用当前x坐标加上汉字的宽度w再加
} //上字间距space来实现;
}
//如果列坐标超出了640,不能再显示下一个汉字时,而汉字又没有显示完,
//则将列坐标重新设置为零,横坐标加上此行汉字的高度再加上4,目的是为了美观;
if(isHorizontal==1) yPosition+=h+space,xPosition=xx;
for( i = 0 ; i < arr_b ; i ++ )
HZKMAT = (unsigned char)(*(ZM+n++));
y0=yPosition+h/8;//ASC显示位置的行坐标暂存,以在显示下一ASC时用;
//h/8 是为了将ASC字符显示位置降一点,以使其更美观;
// if( *HZPTR == ' ' )
// {
// xPosition+=old_w-old_w/2+space;//ASC没汉字宽,所以减去8以缩字距;
// continue;
// }
for( i=0 ; i<h ; i++ ) //按ASC的高度循环;
{
x0=xPosition;//将ASC显示位置的列坐标暂存,以在显示下一条线时用;
pos=w/8*i; // pos用于HZKMAT数组中的下标定位;
for(j=0;j<w-1;j++)//按ASC的宽度循环, w-1是因为ASC没汉字那么宽;
{
if((mask[j%8]&((HZKMAT[pos+j/8])))!=NULL)//按位相与后不为0则画点;
if(slantingflag>=2)putpixel(x0+(h-i),y0,color);//断倾斜标致;
else if(slantingflag==1)putpixel(x0+(h/2-i/2),y0,color);
else putpixel(x0,y0,color); //屏幕当前坐标按颜色值画点;
x0++; //画好后将列坐标加上1;
}
y0++; //一行字模画完后将画下一行,y0++是将行数加1,到下一行;
}
xPosition+=old_w-old_w/2+space;//ASC没汉字宽,所以减去8以缩字距;
HZPTR+=1; //此处的字符指针只移一位,是因为ASC字符只占一个字节;
} //(汉字占两个字节,所以加2);
}
return(0); //返加0值表示没有出错;
} |
|