注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

简约男人

简约,不能简单

 
 
 

日志

 
 
关于我

一个过分渴望被理解的人其实就是一个软弱的人, 勇往直前的力量来自斩钉截铁的决心,不是来自别人的理解.

网易考拉推荐

TC2.0 下汉字的显示(转)  

2009-10-03 16:47:47|  分类: C\C++\C# |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |


我这里是以16*16字模库说明的.
先说明一下原理:
所谓的16*16是一个汉字是存放格式:
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
总共16行16列,每一行占二个字节的空间,
每一个字节的的每一位是0表示不显示,1表示显示.

那如何得到汉字的字模信息呢?难道要我们自己去做?NO。DOS前辈们经过艰辛的努力,将制作好的字模放到了一个个标准的库中以免去后辈的麻烦,这就是点阵字库文件。一般我们使用16*16的点阵宋体字库,所谓16*16,是每一个汉字在纵、横各16点的区域内显示的。不过后来又有了HZK12、HZK24,HZK32和HZK48字库及黑体、楷体和隶书字库。虽然汉字库种类繁多,但都是按照区位的顺序排列的。前一个字节为该汉字的区号,后一个字节为该字的位号。每一个区记录94个汉字,位号则为该字在该区中的位置。因此,汉字在汉字库中的具体位置计算公式为:94*(区号-1)+位号-1。减1是因为数组是以0为开始而区号位号是以1为开始的。这仅为以汉字为单位该汉字在汉字库中的位置,那么,如何得到以字节为单位得到该汉字在汉字库中的位置呢?只需乘上一个汉字字模占用的字节数即可,即:(94*(区号-1)+位号-1)*一个汉字字模占用字节数,而按每种汉字库的汉字大小不同又会得到不同的结果。以16*16点阵字库为例,计算公式则为:(94*(区号-1)+(位号-1))*32。汉字库文该从该位置起的32字节信息即记录了该字的字模信息。

我可以给出一个例程序:
#include "graphics.h"
#include "stdio.h"
main()
{ int i=VGA,j=VGAHI,k;
 unsigned char mat[16][2],chinease[3]="我";
 FILE *HZK;
 if((HZK=fopen("hzk16","rb"))==NULL)exit(0);
 initgraph(&i,&j,"");
 i=chinease[0]-0xa0;j=chinease[1]-0xa0; /*获得区码与位码*/
 fseek(HZK,(94*(i-1)+(j-1))*32l,SEEK_SET); /*将文件指针指向字模的初始位置*/
 fread(mat,32,1,HZK); /*读取一个32个字节长度的信息到mat中*/

/*得到字模后,显示汉字*/
 for(j=0;j<16;j++)
  for(i=0;i<2;i++)
  for(k=0;k<8;k++)
/*扫描这个字节的每一位,如果是1则显示一个点,否则不显示*/
   if(mat[j][i] & (0x80>>k))/*0x80相当于:10000000 和字节作与运算时
如果最高位是1则与运算的结果是1,如果是0则与运算结果为0
0x80>>k是向右移位,当k==1时右移结果:01000000再与运算
如此循环完这个字节*/
   putpixel(i*8+k,j,RED);
getch();
 closegraph();
 fclose(HZK);
}
/*由于刚才上传hzk16字库不成功,要自己下,如果下不到
发信息到zhaoxufeng9997@126.com 我会发给你的*/
若 —— 您仅仅是为了使 C 程序中字符串(或 ASM 程序中的字符串)所包含的汉字能显示出来;
并 —— 您所编写的 C 程序(或 ASM 程序)运行在 Windows 的命令行控制台(cmd/command)中。
若您是为了学习汉字显示技术的原理,则以下介绍的方法并不适合您。


通过更改控制台 (cmd/command)的代码页显示汉字

你可以通过更改控制台的代码页来显示,您可以编写一个简单的程序以佐测试:
#include "stdio.h"
#include "conio.h"

int main(void)
{
printf("通过更改控制台代码页来显示汉字。");
getch();
return 0;
}

以上程序所生成的 EXE 文件在命令行控制台(cmd/command)下执行时显示的是乱码,
在该控制台窗口标题右击,选择[属性],您可以看到[选项]页中的[当前代码页]显示的是:
437 (OEM - 美国)

在 cmd 中,输入命令:chcp
可以查看当前活动的代码页,
您将可以看到是代码页是 936,
这是中文简体的代码页,cmd 启动后默认使用本地语言的代码页,
这也是为什么您能在 cmd 下看到中文及输入中文的原因。
而 TC (或 MASM) 所编译生成的文件是使用 command 来执行的,
command 默认使用的是 437 英文显示字符。

要更改代码页,先打开命令行控制台,(cmd/command),
并使用 graftabl 936 来启动图形屏幕汉字显示支持。
输入以下命令:
chcp 437
graftabl 936
你的程序.exe

您此时便可以看到程序中的中文能正确地显示。
为免麻烦,可以使用以下的批处理文件(myApp.exe 是您待运行的程序):
echo off
chcp 437
graftabl 936
cls
myApp.exe
pause


#include<dos.h>
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<process.h>
#define VGA256 0x13
#define TEXT_MODE 0x03

unsigned char far *video_buffer=(char far *)0xA0000000L;

unsigned char bit[8]={128,64,32,16,8,4,2,1};

void Delay(int clicks)
{
unsigned int far *clock=(unsigned int far *)0x0000046CL;
unsigned int now;
now=*clock;
while(abs(*clock-now)<clicks){}
}


void Plot_Pixel_Fast(int x,int y,char color)
{
video_buffer[((y<<8)+(y<<6))+x]=color;
}

void GetHzBit(char ch0,char ch1,char *bitdata)
{
FILE *stream;
long fpos;
fpos=32L*(((unsigned char)ch0-161)*94+((unsigned char)ch1-161));
if((stream=fopen("hzk16","rb"))==NULL){
printf("Open hzk16 error!\\n");
exit(0);
}
fseek(stream, fpos, SEEK_SET);
fread( bitdata, 32, 1, stream);
fclose(stream);
}

void WriteHz(char ch0,char ch1,int x,int y,int color)
{
register int i,j,k;
unsigned vpos;
char bitdata[32];
GetHzBit(ch0,ch1,bitdata);
for(i=0;i<16;i++)
for(j=0;j<8;j++){
if(bitdata[2*i]&bit[j])
Plot_Pixel_Fast(x+j,i+y,color);
if(bitdata[2*i+1]&bit[j])
Plot_Pixel_Fast(x+8+j,i+y,color);
}
}
void WriteHzStr(char *str,int x,int y,int color)
{
int num,i,j,xx;
unsigned char s0,s1;
num=strlen(str);
xx=x;
for(i=0;i<num;i+=2){
WriteHz(str[i],str[i+1],xx,y,color);
xx+=16;
}
}

void Words_Step(char *str,int x,int y,int color,int speed)
{
int num,i,j,xx;
unsigned char s0,s1;
num=strlen(str);
xx=x;
for(i=0;i<num;i+=2){
WriteHz(str[i],str[i+1],xx,y,color);
Delay(speed);
xx+=16;
}
}

void Set_Video_Mode(int mode)
{
union REGS inregs,outregs;
inregs.h.ah=0;
inregs.h.al=(unsigned char)mode;
int86(0x10,&inregs,&outregs);
}

void main(void)
{
Set_Video_Mode(VGA256);
WriteHzStr("按任意键进入中文渐显:",10,100,WHITE);
getch();
Words_Step("现在文字处于渐显状态。",10,130,WHITE,4);
getch();
Set_Video_Mode(TEXT_MODE);
}

  评论这张
 
阅读(763)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017