returnfalse;
}
returntrue;
}
其中registerbgidriver(EGAVGA_driver)函数用于告诉连接程序,在连接时,把EGAVGA的驱动程
序装入执行程序中。
Initgraph(int*gd,int*gm,char*)函数用于图形系统的初始化。
Gd,gm分别表示图形驱动器和
图形模式。
Gd=DETECT,告诉初始化函数自动探测显示器的类型。
Graphresult(),和grapherrormsg(interrorcode)用于检测图形系统初始化是否正确,若不正确
则打印错误原因。
本程序中的输出全部是在图形模式下,用到了画点(putpixle(intx,inty,intcolor)),画线
(line(intx1,inty1,intx2,inty2),lineto(intx,inty)),坐标移动及提取(moveto(intx,inty),
getx(),gety(),getmaxx(),getmaxy())设置颜色(setcolor(intcolor),setbkcolor(intcolor),
getcolor(),getmaxcolor())画框、设置点线的样式等等。
图形系统的退出用closegraph()函数实现。
鼠标操作简介
1.鼠标简介
鼠标系统实际上由两个主要元素组成:
鼠标机制和称作鼠标驱动程序的内存驻留程序。
鼠
标驱动程序提供与鼠标通信所需的全部低级支持。
此外,它自动维持鼠标光标位置和发现
是否按下了某个键。
一旦装入驱动程序,鼠标就可以被随后执行的任意程序使用。
2.鼠标驱动程序的主要功能
可以通过PC中断33H访问鼠标和鼠标驱动程序的各种功能。
所选择的特定函数依赖于中断
时AX寄存器的值。
三个其它寄存器(BX、CX和DX)用于把各种参数传送给鼠标例程。
同
样,鼠标函数使用这四个寄存器把鼠标的位置和按钮的状态返回给调用函数。
功能
输入值
输出值
功能调用
初始化
无
AXBX
AX=0000
显示光标
无
无
AX=0001
隐藏光标
无
无
AX=0002
读取状态
无
BXCXDX
AX=0003
设置位置
CX、DX
无
AX=0004
设置光标
BXCXDX
无
AX=0009
X范围
CXDX
无
AX=0007
Y范围
CXDX
无
AX=0008
光标范围
CXDXSIDI
无
AX=0010
中断程序
CXES:
DX
无
AX=000C
3.鼠标功能调用方法
用TC通过INT33H中断来编制基本函数,有三种常用方法:
嵌入汇编程序,如:
ASMCLI清中断
利用全程变量赋予寄存器值,然后通过函数geninterrupt()调用中断实现
利用联合类型REGS,SREGS通过函数int86(),int86x()调用中断,原型在在dos.h
注意一下例程中预定义了如下全局变量:
#definetrue1
#definefalse0
intvisual=false;/*totellwhetherthemouseiconisvisualandinitasfalse*/
4.鼠标的初始化
InitMouse()
{unionREGSregs;
regs.x.ax=0;
int86(0x33,®s,®s);
if(regs.x.ax==0)
returnfalse;
elsereturntrue;}
5.鼠标光标的显示与隐藏
HideCur()
{unionREGSregs;
if(visual){
regs.x.ax=2;
int86(0x33,®s,®s);
visual=false;
}}
ShowCur()
{unionREGSregs;
if(!
visual){
regs.x.ax=1;
int86(0x33,®s,®s);
visual=true;
}}
在鼠标驱动程序中,鼠标的显示状态用0值表示,隐藏用负值表示,每调用一次显示功能
则该值加一,每调用一次隐藏功能,则该值减一。
这样,在多次调用了驱动程序的隐藏鼠
标光标功能后,再调用显示鼠标光标功能时,将不能正常显示鼠标光标。
需要加入了一个
visual布尔型变量,来取代驱动程序中的数值。
6.读取按钮状态,读取或设置光标位置
Status(int*x,int*y,int*status)
{unionREGSregs;
regs.x.ax=3;
int86(0x33,®s,®s);
*x=regs.x.cx;
*y=regs.x.dx;
*status=regs.x.bx;
}其中X,Y为光标位置
status&1左键状态,1为按下,0为未按
status&2右键状态,1为按下,0为未按
status&4中键状态,1为按下,0为未按
要注意循环检测时的抖动现象,可增加一些空循环或延时来清除剩余的按键信号。
例如:
下面程序段,当鼠标移动时画线到当前的鼠标位置,当按左键时定义画线的启始位
置,按右键时结束作图。
intworking=true;
intx,y,status;
while(working){
Status(&x,&y,&status);
If(status&1)/*leftbuttonpressed*/
moveto(x,y);/*movetocurrentmouseposition*/
Elseif(status&2)/*rightbuttonpressed,quit*/
Working=false;
Else/*nobuttonpressed*/
Lineto(x,y);/*drawalinefromlastposition*/
Delay(20);/*delay20mstoclearthedithering*/
}
7.移动鼠标光标
voidMoveMouse(intx,inty)
{REGSregs;
regs.x.ax=4;
regs.x.cx=x;
regs.x.dx=y;
int86(0x33,®s,®s);
}
8.设置鼠标的光标形状
设置鼠标光标需要三个方面信息:
鼠标的外边界:
8*8点阵,16个整数
鼠标的内部形状:
8*8点阵,16个整数
以及鼠标的热点的相对坐标:
intx,y
其中外边界和内边界连续存放,为长度为32的整型数组intmarks[32]SetCurs(unsigned
masks[32],x,y)
{unionREGSregs;structSREGSsregs;
regs.x.ax=9;
regs.x.bx=x;regs.x.cx=y;/*hotspot*/
regs.x.dx=(unsigned)masks;
segread(&sregs);int86(0x33,®s,®s);
}
一些不同形状的光标数据:
//mouse
{0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,//Cursormask
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1000,0x13c0,
0x3ff0,0x7ff8,0xfff8,0xfff8,0x0824,0x0822,0x1ce2,0x0000},
//emptyhand
{0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
0x0c00,0x1200,0x1200,0x1200,0x13fe,0x1249,0x1249,0x1249,
0x7249,0x9001,0x9001,0x9001,0x8001,0x8001,0x4002,0x3ffc},
//fullarrow
{0x3fff,0x1fff,0x0fff,0x07ff,0x03ff,0x01ff,0x00ff,0x007f,
0x003f,0x00ff,0x01ff,0x10ff,0x30ff,0xf87f,0xf87f,0xfc3f,
0x0000,0x4000,0x6000,0x7000,0x7800,0x7c00,0x7e00,0x7f00,
0x7f80,0x7e00,0x7c00,0x4600,0x0600,0x0300,0x0300,0x0180},
//fullhand
{0xf3ff,0xe1ff,0xe1ff,0xe1ff,0xe001,0xe000,0xe000,0xe000,
0x8000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8001,0xc003,
0x0c00,0x1200,0x1200,0x1200,0x13fe,0x1249,0x1249,0x1249,
0x7249,0x9001,0x9001,0x9001,0x8001,0x8001,0x4002,0x3ffc}
};
Pointhotspot[]={{0,11},{4,0},{0,0},{4,0}};/*热点*/
9.设置鼠标光标的移动范围
SetMouseArea(intx0,inty0,intx1,inty1)
{unionREGSregs;
regs.x.ax=7;regs.x.cx=x0;regs.x.dx=x1;
int86(0x33,®s;®s);
regs.x.ax=8;regs.x.cx=y0;regs.x.dx=y1;
int86(0x33,®s,®s);
}
西文状态下汉字的显示
1.汉字库简介
程序中直接使用UCDOS中的HZK16,ASC16和HZK24三个文件。
HZK16中存储的是16*16点阵汉字是按行存储的以便于显示,每个汉字字模32BYTE,按照
国标码顺序存储,其中也包含了682个纯中文符号字母。
ASC16存储256个西文ASCII码的
8*16点阵格式,按行存储,每个ASCII码16字节。
HZK24X存储24*24点阵打印字模,按列存储,每个汉字字模占576字节。
24*24点阵汉字
存储两比较大,所以从16区1位"啊"字开始存储,以减少字库大小。
其中X为KS表示楷体,
宋体等。
2.取得字节的某一位
intgetbit(unsignedcharbyte,intbit)
{if(bit<0||bit>7)
return0;
return(byte>>bit)&0x1;
}
函数getbit用于得出一个字节中每个位(bit)是0还是1。
3.显示24点阵和16点阵汉字
voidPutChn24(x,y,char*by,color)
{inti1,i2,i3;
for(i1=0;i1<24;i1++)//LINES
for(i2=0;i2<3;i2++)//3bytesperline
for(i3=0;i3<8;i3++)
if(getbit(by[i1*3+i2],7-i3))
putpixel(x+i1,y+(i2*8+i3),color);}
voidPutChn16(x,y,char*buf,color)
{inti1,i2,i3;
for(i1=0;i1<16;i1++)
for(i2=0;i2<2;i2++)
for(i3=0;i3<8;i3++)
if(getbit(buf[i1*2+i2],7-i3))
putpixel(x+i2*8+i3,y+i1,color);}qu=c1-0xa1;wei=c2-0xa1;
4.在字库中取字模
通过计算个计算出该区位码在汉字库中的偏移量:
lenth=32
longoffset=((qu)*94+wei)*(long)lenth;
24*24点阵汉字字模的读取类似,只是其偏移量计算稍有不同:
lenth=72
longoffset=((qu-15)*94+wei)*(long)lenth;
5.参考部分论文
其中的字模的或取如下,三个函数是类FileStream中的成员函数:
constunsignedchar*FileStream:
:
GetBigFnt(constChinese&c)
{
if(buffer){
delete[]buffer;
buffer=NULL;
}
lenth=72;
buffer=newunsignedchar[lenth];
if(!
buffer){
cerr<<'\a'<<"Notenoughmemoryerror!
"<returnbuffer=NULL;
}
intqu=c.c.c1-0xa1;
intwei=c.c.c2-0xa1;
longoffset=((qu-15)*94+wei)*(long)lenth;
bigfnt.clear();
bigfnt.seekg(offset,ios:
:
beg);
bigfnt.read(buffer,lenth);
intcount=bigfnt.gcount();
cout.setf(ios:
:
dec);
//coutendl<<"gcount="<if(count!
=lenth){
cerr<<"\n\aCharacternotmatchin"<"<bigfnt.clear();
lenth=0;
delete[]buffer;
returnbuffer=NULL;
}
returnbuffer;
}
constunsignedchar*FileStream:
:
GetSmallFnt(constChinese&c)
{
if(buffer){
delete[]buffer;
buffer=NULL;
}
lenth=32;
buffer=newunsignedchar[lenth];
if(!
buffer){
cerr<<'\a'<<"Notenoughmemoryerror!
"<returnbuffer=NULL;
}
intqu=c.c.c1-0xa1;
intwei=c.c.c2-0xa1;
longoffset=((qu)*94+wei)*(long)lenth;
smallfnt.clear();//clearlasttime'serrorstate
smallfnt.seekg(offset,ios:
:
beg);//locate
smallfnt.read(buffer,lenth);//readtobuffer
intcount=smallfnt.gcount();
////cout<if(count!
=lenth){
cerr<<"\n\aCharacternotmatchin"<"<smallfnt.clear();//clearlasttime'serrorstate
lenth=0;
delete[]buffer;
returnbuffer=NULL;
}
returnbuffer;
}
几个函数中用了较多的语句进行“文件流”fstream的操作,和内存的动态申请释放及存取,也用
了较多的命令来容错。
函数GetSmallFnt(c)的功能是从文件HZK16中取出32字节的汉字c的字模。
汉
字Chinesec是一个共用体,其中包含两个字节,及该汉字的内码。
每个字节减去0XA0后变成区位码。
及:
intqu=c.c.c1-0xa1;
intwei=c.c.c2-0xa1;
通过计算个计算出该区位码在汉字库中的偏移量:
longoffset=((qu)*94+wei)*(long)lenth;
然后通过文件定位和文件读取可得到该字模代码。
24*24点阵汉字字模的读取类似,只是其偏移量计算稍有不同
longoffset=((qu-15)*94+wei)*(long)lenth;
下面两个函数用于在屏幕上一个位置开始,以一个颜色显示16*16点阵和24*24点阵的汉字字符串。
其中用到了上面的PutChn16和PutChn24两个函数。
由于一个汉字的存储需要两个字节,所以在一个字符
串中处理汉字,在遇到一个字符时,首先要判断该字符是常规的ASCII字符(首位为“0”)还是用于汉字
的字符(首位为“1”),其次如果首位为“1”,还要判断该字符是该汉字的第一个字符(flag==0),还是
第二个字符(flag==1),再将表示一个汉字的两个字符组合成一个汉字并显示。
如果遇到空格还要空出一
个字符的位置。
如果遇到常规ASCII字符还要用PutAsc16显示(本程序暂时未考虑AS