用BASIC语言设计Windows风格的用户接口
2006-02-27 21:15:06 来源:WEB开发网核心提示:BASIC语言历史悠久,近年来发展迅速,BASIC语言的结构化程度高,易于理解,很适合广大的编程人员使用,用BASIC语言设计Windows风格的用户接口,而第三代BASIC语言的功能更是日臻完善、强大,使用人员更多,本文意在向编程经验不十分丰富的读者介绍用BASIC语言设计Windows风格的图形用户接口,起一点抛砖
BASIC语言历史悠久,近年来发展迅速。BASIC语言的结构化程度高,易于理解,很适合广大的编程人员使用。而第三代BASIC语言的功能更是日臻完善、强大,使用人员更多。
本文意在向编程经验不十分丰富的读者介绍用BASIC语言设计Windows风格的图形用户接口,起一点抛砖引玉的作用,不妥之处望不吝赐教。程序
在VGA(用Screen12语句设置)方式下运行,可在QuickBASIC、MSBASIC或VisualBASICforMS-DOS下编译。另外需要说明的是程序中设置颜色使用的都是调色板位置号,一个调色板位置号并不固定代表某种特定颜色,而是可以由编程者通过PALETTE语句或PALETTEUSING语句自行指定的。当然,一般情况下我们使用系统缺省的调色板颜色。
1.读点阵字模交叉显示汉字及ASCII字符。
这里要用到UCDOS3.1的HZK16和ASC16两个字模文件,该功能模块的代码如下:
SUBDispHz(HzCol,HzRow,Color,HzStr$)
DIMi1,i2,i3,I,c1,c2,f,g,HzChar,AscCharASINTEGER
DIMHzByASSTRING*32
DIMAscByASSTRING*16
DIMl,HzRecASLONG
OPEN"HZK16"FORBINARYAS#1`打开汉字库文件
OPEN"ASC16"FORBINARYAS#2`打开ASCII码字库文件
HzLen=LEN(HzStr$)`计算字符串长度
HzPos=1`置字符串的首字节为当前字节
WHILEHzPos<=HzLen`字符串显示完前一直循环
I=ASC(MID$(HzStr$,HzPos,1))`获取当前字符的ASCII值
IFI>&HA0THEN`判断是否为汉字内码
IFf=0THEN`f为零则该字节为汉字区码
c1=I-&HA1`计算区码
f=-1`置f为非零
ELSE`f不为零则该字节为汉字位码
c2=I-&HA1`计算位码
f=0`置f为零
HzRec=c1*94 c2`计算汉字在字库中的记录号
l=HzRec*32 1`计算汉字在字库中的起始字节位置
GET#1,l,HzBy`从l开始读取32字节
FORi1=0TO15`字模垂直方向16行点
FORi2=0TO1`每行16个点对应的两个字节
HzChar=ASC(MID$(HzBy,i1*2 i2 1,1))`每个字节的ASCII值
FORi3=0TO7`每个字节的8位
IF(HzChar(2&(7-i3)))AND&H1THEN`若该位是1
PSET(HzCol i2*8 i3,HzRow i1),Color`画点
ENDIF
NEXTi3
NEXTi2
NEXTi1
HzCol=HzCol 16`将光标置于下一个字符的左上角
ENDIF
ELSE`不是汉字内码则为ASCII码
l=I*16 1`计算ASCII字符在字库中的起始字节位置
GET#2,l,AscBy`从l开始读取16字节
FORi1=0TO15
`字模垂直方向16行点,每行对应1个字节
AscChar=ASC(MID$(AscBy,i1 1,1))`每个字节的ASCII值
FORi3=0TO7`每个字节的8位
IF(AscChar(2&(7-i3)))AND&H1THEN`若该位是1
PSET(HzCol i3,HzRow i1),Color`画点
ENDIF
NEXTi3
NEXTi1
HzCul=HzCul 8`光标置于下一个字符的左上角
ENDIF
HzPos=HzPos 1`置字符串的下一个字节为当前字节
WEND
CLOSE
ENDSUB
参数HzCol、HzRow是所要显示字符串的左上角坐标,Color是字符串的颜色,HzStr$是要显示的字符串,其中可包含汉字、图形符号和ASCII字符。
2.Windows风格图形界面。
Windows界面简洁、美观、标准,用BASIC语言的图形函数可以很方便地生成一个Windows风格界面。
先用VIEW(0,0)-(639,479),3设置背景色,再调用下面的过程生成窗口,调用一次生成一个窗口。参数Le、Top、Ri、Bo指定窗口左上角和右下角的坐标,FrmCol、TitCol是工作区和标题栏背景色,Title$、Menu$是标题和菜单的文字内容。例如,以下调用将生成一个主窗口和一个子窗口:
MyForm30,30,609,440,7,4,"程序主窗口","文件[F]选项[O]窗口[W]帮助[H]"
MyForm70,90,569,400,15,1,"程序子窗口","文件[F]编辑[E]搜索[S]运行[R]帮助[H]"
过程代码如下:
SUBMyForm(Le,Top,Ri,Bo,FrmCol,TitCol,Title$,Menu$)
x=Ri-Le:y=Bo-Top
VIEW(Le,Top)-(Ri,Bo),
LINE(0,0)-(x,y),0,B`画窗体
LINE(3,3)-(x-3,y-3),0,
LINE(0,22)-(x,22),
LINE(4,41)-(x-4,41),
PAINT(30,30),15,0`填充颜色
PAINT(30,10),TitCol,
PAINT(10,50),FrmCol,
VIEW(Le 3,Top 3)-(Le 22,Top 22),
LINE(0,0)-(19,19),0,B`画控制钮
LINE(4,9)-(16,11),8,
LINE(3,8)-(15,10),0,
LINE(4,9)-(14,9),15
VIEW(Le,Top)-(Ri,Bo)
DispHz(x-LEN(Title$)*8)/2-9,5,15,Ti-tle$`标题
DispHz12,23,0,Menu$`主菜单
ENDSUB
用类似方法还可以生成其它Windows风格部件,包括三维风格部件。
3.下拉菜单
下拉菜单是通过用GET语句保存菜单弹出前的屏幕内容,用PUT语句恢复先前保存的屏幕内容实现的,有关内容许多书上都有介绍,这里不再赘述。
4.键盘和鼠标控制
键盘和鼠标操作通过BIOS中断调用的循环检测来实现。
INT16H是键盘中断、INT33H是Microsoft鼠标中断,通过这两个中断的功能调用就可以分别用键盘和鼠标控制程序。仅仅使用键盘操作的程序在需要键盘控制时可以用INT16H的功能00H在键盘缓冲区中无键入码时等待键盘输入,一旦有键入码就读取并进行相应处理。倘若还要同时使用鼠标进行程序控制,就不能用这种终止程序运行等待用户操作的方法,这是因为程序要不断查询鼠标驱动程序以实时确定鼠标的状态。为此可以在每次循环内调用INT16H的功能00H前,先调用功能01H弄清键盘缓冲区中是否有按键等待处理,若无则不执行对功能00H的调用,直接执行鼠标功能。限于篇幅这里只简单举例说明,读者可照此在自己的程序中加入响应特定键盘按键和鼠标输入的代码,实现对程序的"键盘-鼠标"双重控制。
先定义键盘和鼠标的中断调用模块:
STATICSUBKeyStroke(k0,k1,k2)
DIMregsASRegType
regs.ax=k0
INTERRUPT&H16,regs,regs
k1=regs.ax
k2=regs.flagsAND&H40`得到标志寄存器的零标志位
ENDSUB
STATICSUBMouDrv(m0,m1,m2,m3)
DIMregsASRegType
regs.ax=m0
regs.bx=m1
regs.cx=m2
regs.dx=m3
INTERRUPT&H33,regs,regs
m0=regs.ax
m1=regs.bx
m2=regs.cx
m3=regs.dx
ENDSUB
函数MouPoll用来查询鼠标光标的坐标和左右按键是否被按下:
STATICSUBMouPoll(row,col,lButton,rButton)
MouDrv3,button,col,row
IFButtonAND1THENlButton=-1ELSElButton=
IFButtonAND2THENrButton=-1ELSErButton=
ENDSUB
下面是本例的主程序,其中的循环将实时检测且在屏幕上显示键盘击键的ASCII键值和扫描码、鼠标按键状况和光标坐标,程序将一直运行直到按了"Alt-X"为止。
`$INCLUDE:`QBX.BI`
MouDrv0,0,0,0`初始化鼠标驱动程序
MouDrv1,0,0,0`显示鼠标光标
LOCATE16,1:PRINT"Press`Alt-X`toendprogram."
WHILE(NOTAlt_X)
KeyStroke&H100,Code,ZF`检查是否有击键码
IFZF=0THEN`零标志位是零表示有击键可用
KeyStroke&H0,Code,ZF`取得击键
KeyCode=CodeAND&HFF`取出击键的ASCII键值
ScanCode=(CodeAND&HFF00)256`取出击键的扫描码
IFScanCode=45THENAltlt_X=-1`按"Alt-X"键则退出循环
LOCATE18,1:PRINT"KeyCode:";KeyCode
LOCATE19,1:PRINT"ScanCode:";ScanCode
ELSE`零标志位是1表示无击键可用,进入鼠标例程
MouPollrow,col,lButton,rButton`取得鼠标状态
IFlButtonTHEN`左键按下
Button$="Left
ELSEIFrButtonTHENButton$="Right"`右键按下
ELSEButton$="None"`左右键均未按下
ENDIF
LOCATE21,1:PRINT"Button:";Button$
LOCATE22,1:PRINT"Position:";row;",";col
ENDIF
WEND
MouDrv2,0,0,0`隐藏鼠标光标->
本文意在向编程经验不十分丰富的读者介绍用BASIC语言设计Windows风格的图形用户接口,起一点抛砖引玉的作用,不妥之处望不吝赐教。程序
在VGA(用Screen12语句设置)方式下运行,可在QuickBASIC、MSBASIC或VisualBASICforMS-DOS下编译。另外需要说明的是程序中设置颜色使用的都是调色板位置号,一个调色板位置号并不固定代表某种特定颜色,而是可以由编程者通过PALETTE语句或PALETTEUSING语句自行指定的。当然,一般情况下我们使用系统缺省的调色板颜色。
1.读点阵字模交叉显示汉字及ASCII字符。
这里要用到UCDOS3.1的HZK16和ASC16两个字模文件,该功能模块的代码如下:
SUBDispHz(HzCol,HzRow,Color,HzStr$)
DIMi1,i2,i3,I,c1,c2,f,g,HzChar,AscCharASINTEGER
DIMHzByASSTRING*32
DIMAscByASSTRING*16
DIMl,HzRecASLONG
OPEN"HZK16"FORBINARYAS#1`打开汉字库文件
OPEN"ASC16"FORBINARYAS#2`打开ASCII码字库文件
HzLen=LEN(HzStr$)`计算字符串长度
HzPos=1`置字符串的首字节为当前字节
WHILEHzPos<=HzLen`字符串显示完前一直循环
I=ASC(MID$(HzStr$,HzPos,1))`获取当前字符的ASCII值
IFI>&HA0THEN`判断是否为汉字内码
IFf=0THEN`f为零则该字节为汉字区码
c1=I-&HA1`计算区码
f=-1`置f为非零
ELSE`f不为零则该字节为汉字位码
c2=I-&HA1`计算位码
f=0`置f为零
HzRec=c1*94 c2`计算汉字在字库中的记录号
l=HzRec*32 1`计算汉字在字库中的起始字节位置
GET#1,l,HzBy`从l开始读取32字节
FORi1=0TO15`字模垂直方向16行点
FORi2=0TO1`每行16个点对应的两个字节
HzChar=ASC(MID$(HzBy,i1*2 i2 1,1))`每个字节的ASCII值
FORi3=0TO7`每个字节的8位
IF(HzChar(2&(7-i3)))AND&H1THEN`若该位是1
PSET(HzCol i2*8 i3,HzRow i1),Color`画点
ENDIF
NEXTi3
NEXTi2
NEXTi1
HzCol=HzCol 16`将光标置于下一个字符的左上角
ENDIF
ELSE`不是汉字内码则为ASCII码
l=I*16 1`计算ASCII字符在字库中的起始字节位置
GET#2,l,AscBy`从l开始读取16字节
FORi1=0TO15
`字模垂直方向16行点,每行对应1个字节
AscChar=ASC(MID$(AscBy,i1 1,1))`每个字节的ASCII值
FORi3=0TO7`每个字节的8位
IF(AscChar(2&(7-i3)))AND&H1THEN`若该位是1
PSET(HzCol i3,HzRow i1),Color`画点
ENDIF
NEXTi3
NEXTi1
HzCul=HzCul 8`光标置于下一个字符的左上角
ENDIF
HzPos=HzPos 1`置字符串的下一个字节为当前字节
WEND
CLOSE
ENDSUB
参数HzCol、HzRow是所要显示字符串的左上角坐标,Color是字符串的颜色,HzStr$是要显示的字符串,其中可包含汉字、图形符号和ASCII字符。
2.Windows风格图形界面。
Windows界面简洁、美观、标准,用BASIC语言的图形函数可以很方便地生成一个Windows风格界面。
先用VIEW(0,0)-(639,479),3设置背景色,再调用下面的过程生成窗口,调用一次生成一个窗口。参数Le、Top、Ri、Bo指定窗口左上角和右下角的坐标,FrmCol、TitCol是工作区和标题栏背景色,Title$、Menu$是标题和菜单的文字内容。例如,以下调用将生成一个主窗口和一个子窗口:
MyForm30,30,609,440,7,4,"程序主窗口","文件[F]选项[O]窗口[W]帮助[H]"
MyForm70,90,569,400,15,1,"程序子窗口","文件[F]编辑[E]搜索[S]运行[R]帮助[H]"
过程代码如下:
SUBMyForm(Le,Top,Ri,Bo,FrmCol,TitCol,Title$,Menu$)
x=Ri-Le:y=Bo-Top
VIEW(Le,Top)-(Ri,Bo),
LINE(0,0)-(x,y),0,B`画窗体
LINE(3,3)-(x-3,y-3),0,
LINE(0,22)-(x,22),
LINE(4,41)-(x-4,41),
PAINT(30,30),15,0`填充颜色
PAINT(30,10),TitCol,
PAINT(10,50),FrmCol,
VIEW(Le 3,Top 3)-(Le 22,Top 22),
LINE(0,0)-(19,19),0,B`画控制钮
LINE(4,9)-(16,11),8,
LINE(3,8)-(15,10),0,
LINE(4,9)-(14,9),15
VIEW(Le,Top)-(Ri,Bo)
DispHz(x-LEN(Title$)*8)/2-9,5,15,Ti-tle$`标题
DispHz12,23,0,Menu$`主菜单
ENDSUB
用类似方法还可以生成其它Windows风格部件,包括三维风格部件。
3.下拉菜单
下拉菜单是通过用GET语句保存菜单弹出前的屏幕内容,用PUT语句恢复先前保存的屏幕内容实现的,有关内容许多书上都有介绍,这里不再赘述。
4.键盘和鼠标控制
键盘和鼠标操作通过BIOS中断调用的循环检测来实现。
INT16H是键盘中断、INT33H是Microsoft鼠标中断,通过这两个中断的功能调用就可以分别用键盘和鼠标控制程序。仅仅使用键盘操作的程序在需要键盘控制时可以用INT16H的功能00H在键盘缓冲区中无键入码时等待键盘输入,一旦有键入码就读取并进行相应处理。倘若还要同时使用鼠标进行程序控制,就不能用这种终止程序运行等待用户操作的方法,这是因为程序要不断查询鼠标驱动程序以实时确定鼠标的状态。为此可以在每次循环内调用INT16H的功能00H前,先调用功能01H弄清键盘缓冲区中是否有按键等待处理,若无则不执行对功能00H的调用,直接执行鼠标功能。限于篇幅这里只简单举例说明,读者可照此在自己的程序中加入响应特定键盘按键和鼠标输入的代码,实现对程序的"键盘-鼠标"双重控制。
先定义键盘和鼠标的中断调用模块:
STATICSUBKeyStroke(k0,k1,k2)
DIMregsASRegType
regs.ax=k0
INTERRUPT&H16,regs,regs
k1=regs.ax
k2=regs.flagsAND&H40`得到标志寄存器的零标志位
ENDSUB
STATICSUBMouDrv(m0,m1,m2,m3)
DIMregsASRegType
regs.ax=m0
regs.bx=m1
regs.cx=m2
regs.dx=m3
INTERRUPT&H33,regs,regs
m0=regs.ax
m1=regs.bx
m2=regs.cx
m3=regs.dx
ENDSUB
函数MouPoll用来查询鼠标光标的坐标和左右按键是否被按下:
STATICSUBMouPoll(row,col,lButton,rButton)
MouDrv3,button,col,row
IFButtonAND1THENlButton=-1ELSElButton=
IFButtonAND2THENrButton=-1ELSErButton=
ENDSUB
下面是本例的主程序,其中的循环将实时检测且在屏幕上显示键盘击键的ASCII键值和扫描码、鼠标按键状况和光标坐标,程序将一直运行直到按了"Alt-X"为止。
`$INCLUDE:`QBX.BI`
MouDrv0,0,0,0`初始化鼠标驱动程序
MouDrv1,0,0,0`显示鼠标光标
LOCATE16,1:PRINT"Press`Alt-X`toendprogram."
WHILE(NOTAlt_X)
KeyStroke&H100,Code,ZF`检查是否有击键码
IFZF=0THEN`零标志位是零表示有击键可用
KeyStroke&H0,Code,ZF`取得击键
KeyCode=CodeAND&HFF`取出击键的ASCII键值
ScanCode=(CodeAND&HFF00)256`取出击键的扫描码
IFScanCode=45THENAltlt_X=-1`按"Alt-X"键则退出循环
LOCATE18,1:PRINT"KeyCode:";KeyCode
LOCATE19,1:PRINT"ScanCode:";ScanCode
ELSE`零标志位是1表示无击键可用,进入鼠标例程
MouPollrow,col,lButton,rButton`取得鼠标状态
IFlButtonTHEN`左键按下
Button$="Left
ELSEIFrButtonTHENButton$="Right"`右键按下
ELSEButton$="None"`左右键均未按下
ENDIF
LOCATE21,1:PRINT"Button:";Button$
LOCATE22,1:PRINT"Position:";row;",";col
ENDIF
WEND
MouDrv2,0,0,0`隐藏鼠标光标->
更多精彩
赞助商链接