TC下简单的鼠标驱动框架
如果要调试这个程序,请先阅读下面这段^_^经常泡在VC里亦或是Linux里,好久没写TC了,看到有人问起鼠标的事,闲来无事就写个完完。呵呵,真的好久没写了,很多东西忘记了,查阅了很多以前的代码,理了一个简单的框架出来,很简单,适合在TC下做一些简单的小游戏。
这个程序300多行,因为在TC下写,所以注视都是英文写的,虽然满篇的语法错误,但也能看,呵呵。英文高手指点一下啊。如果里面有些中文写的注视的话,那是在发帖子的时候写上的。
整个程序的功能是一个简单的画图工具,鼠标左键按下后可以画图,右键可以清除画布,键盘上的ESC键可以退出程序,按键盘上的p键可以选择画笔的颜色。
本来这个程序是可以分两个文件,前半部分是框架库,后半部分是调用库赖写的程序,为了贴出来方便就写在一起了现在。
另外这个程序使使用VGA模式写的,所以需要TC提供的BGI驱动文件,我程序里没写驱动路径,所以要调试这个程序的话请将TC3.0文件夹下的/bgi目录下的EGAVGA.BGI文件复制到/bin目录下,如果自己定义的输出目录的话,请复制到自己定的输出目录,也许是/output,如果不想复制驱动文件,可以改我的代码,initgraph(&gd,gm,NULL);改为initgraph(&gd,gm,"../bgi");
以下下是程序清单,在TC3.0下编译通过,程序结束后,又惯于框架的简单介绍。
代码:
/******************
Author: Kelvin Che
Date: 2007-12-30
Compile by TC 3.0
*******************/
#include <stdio.h>
#include <dos.h>
#include <bios.h>
#include <malloc.h>
#include <graphics.h>
/*Some macro for mouse driver.*/
#define __ResetMouse() __regs.x.ax = 0,int86(0x33,&__regs,&__regs)
#define __CheckMouse() __regs.x.ax = 3,int86(0x33,&__regs,&__regs)
#define __GetMouseX() __regs.x.cx
#define __GetMouseY() __regs.x.dx
#define __GetMouseButton() __regs.x.bx
#define __LeftButton() __regs.x.bx & 0x0001
#define __RightButton() __regs.x.bx & 0x0002
/*Bind the proccess to the event handle by this macro.*/
#define BindEvent(handle,proccess) (handle) = (proccess)
/*Some macro for Drawing cursor on screen.*/
#define __DrawCursor(x,y) setcolor(15);\
line((x),(y),(x)+9,(y)+9);\
line((x),(y)+1,(x)+8,(y)+9);\
line((x)+1,(y),(x)+9,(y)+8);\
line((x),(y),(x)+8,(y)+3);\
line((x),(y),(x)+3,(y)+8);\
line((x)+3,(y)+5,(x)+3,(y)+6);\
line((x)+5,(y)+3,(x)+6,(y)+3)
#define __StoreCursorBack(x,y) getimage((x),(y),(x)+9>639?639:(x)+9,(y)+9,__bkimage)
#define __DrawCursorBack(x,y) putimage((x),(y),__bkimage,COPY_PUT)
/*Just like the name.*/
typedef struct tagMouseEventArg
{
int x;
int y;
int leftButton;
int rightButton;
}MouseEventArg;
/*The global mouse event argment.*/
MouseEventArg __mArg;
/*The image of the background under the cursor.*/
void far *__bkimage;
/*Some event handle for user.*/
void (*_FrameOnLoad)() = NULL; /*When the frame begin running.*/
void (*_FrameOnClose)() = NULL; /*When the frame close.*/
int (*_MouseMove)(MouseEventArg e) = NULL; /*When the mouse is moving.*/
int (*_LeftButtonDown)(MouseEventArg e) = NULL; /*Just like the name.*/
int (*_LeftButtonUp)(MouseEventArg e) = NULL;
int (*_RightButtonDown)(MouseEventArg e) = NULL;
int (*_RightButtonUp)(MouseEventArg e) = NULL;
int (*_KeyPress)(int keyCode) = NULL;
/*The union of CPU registers.*/
union REGS __regs;
/*Initialize the VGA graphics mode.*/
void __InitGraph()
{
int gd = VGA, gm = VGAHI;
initgraph(&gd,&gm,NULL);
}
/*Close the graphics mode.*/
void __CloseGraph()
{
closegraph();
}
/*Some functions for event.*/
void __FrameOnLoad()
{
if (_FrameOnLoad)
_FrameOnLoad();
}
void __FrameOnClose()
{
farfree(__bkimage);
if (_FrameOnClose)
_FrameOnClose();
}
int __MouseMove(int x, int y, int l, int r)
{
if (_MouseMove)
{
__mArg.x = x;
__mArg.y = y;
__mArg.leftButton = l;
__mArg.rightButton = r;
return _MouseMove(__mArg);
}
else
return 0;
}
int __LeftButtonDown(int x, int y, int r)
{
if (_LeftButtonDown)
{
__mArg.x = x;
__mArg.y = y;
__mArg.leftButton = 1;
__mArg.rightButton = r;
return _LeftButtonDown(__mArg);
}
else
return 0;
}
int __LeftButtonUp(int x, int y, int r)
{
if (_LeftButtonUp)
{
__mArg.x = x;
__mArg.y = y;
__mArg.leftButton = 1;
__mArg.rightButton = r;
return _LeftButtonUp(__mArg);
}
else
return 0;
}
int __RightButtonDown(int x, int y, int l)
{
if (_RightButtonDown)
{
__mArg.x = x;
__mArg.y = y;
__mArg.leftButton = l;
__mArg.rightButton = 2;
return _RightButtonDown(__mArg);
}
else
return 0;
}
int __RightButtonUp(int x, int y, int l)
{
if (_RightButtonUp)
{
__mArg.x = x;
__mArg.y = y;
__mArg.leftButton = l;
__mArg.rightButton = 2;
return _RightButtonUp(__mArg);
}
else
return 0;
}
int __KeyPress(int keyCode)
{
if (_KeyPress)
return _KeyPress(keyCode);
else if (keyCode == 0x11b)
return -1;
return 0;
}
/*Init the global images.*/
void __InitImages()
{
unsigned int cursorSize;
cursorSize = imagesize(0,0,9,9);
__bkimage = (void far *)farmalloc(cursorSize);
}
/*Start the messages loop.*/
void RunFrame()
{
int ox, oy, ol, or, nx, ny, nl, nr;
int key;
__InitGraph();
__InitImages();
__FrameOnLoad();
__ResetMouse();
__CheckMouse();
ox = __GetMouseX();
oy = __GetMouseY();
ol = __LeftButton();
or = __RightButton();
__StoreCursorBack(ox,oy);
__DrawCursor(ox,oy);
while(1)
{
__CheckMouse();
nx = __GetMouseX();
ny = __GetMouseY();
nl = __LeftButton();
nr = __RightButton();
if (nx != ox || ny != oy)
{
__DrawCursorBack(ox,oy);
if (__MouseMove(nx,ny,nl,nr) == -1)
{
__FrameOnClose();
break;
}
__StoreCursorBack(nx,ny);
__DrawCursor(nx,ny);
}
if (nl && !ol)
{
__DrawCursorBack(nx,ny);
if (__LeftButtonDown(nx,ny,nr) == -1)
{
__FrameOnClose();
break;
}
__StoreCursorBack(nx,ny);
__DrawCursor(nx,ny);
}
else if (!nl && ol)
{
__DrawCursorBack(nx,ny);
if (__LeftButtonUp(nx,ny,nr) == -1)
{
__FrameOnClose();
break;
}
__StoreCursorBack(nx,ny);
__DrawCursor(nx,ny);
}
if (nr && !or)
{
__DrawCursorBack(nx,ny);
if (__RightButtonDown(nx,ny,nl) == -1)
{
__FrameOnClose();
break;
}
__StoreCursorBack(nx,ny);
__DrawCursor(nx,ny);
}
else if (!nr && or)
{
__DrawCursorBack(nx,ny);
if (__RightButtonUp(nx,ny,nl) == -1)
{
__FrameOnClose();
break;
}
__StoreCursorBack(nx,ny);
__DrawCursor(nx,ny);
}
if (bioskey(1))
{
__DrawCursorBack(nx,ny);
if (__KeyPress(bioskey(0)) == -1)
{
__FrameOnClose();
break;
}
__StoreCursorBack(nx,ny);
__DrawCursor(nx,ny);
}
ox = nx;
oy = ny;
ol = nl;
or = nr;
}
__CloseGraph();
}
/*****************************
此处以上是框架库,下面的事调用库赖写的程序。
*****************************/
int x, y;
int backColor, penColor;
void OnLoad()
{
int imageSize;
setfillstyle(SOLID_FILL,backColor);
bar(0,0,639,479);
}
int Start(MouseEventArg e)
{
x = e.x;
y = e.y;
putpixel(x,y,penColor);
return 0;
}
int End(MouseEventArg e)
{
x = y = -1;
return 0;
}
int Draw(MouseEventArg e)
{
if (e.leftButton && x != -1 && y != -1)
{
setcolor(penColor);
line(x,y,e.x,e.y);
x = e.x;
y = e.y;
}
return 0;
}
int Clear(MouseEventArg e)
{
setfillstyle(SOLID_FILL,backColor);
bar(0,0,639,479);
}
int SelectPen(MouseEventArg e)
{
if (e.x > 74 && e.x < 75+29+15*30+1 && e.y > 224 && e.y <225+29+1)
{
penColor = (e.x-75)/30;
setfillstyle(SOLID_FILL,backColor);
bar(0,0,639,479);
BindEvent(_LeftButtonDown,Start);
BindEvent(_LeftButtonUp,End);
BindEvent(_MouseMove,Draw);
BindEvent(_RightButtonUp,Clear);
}
return 0;
}
int KeyPress(int keyCode)
{
int i;
if (keyCode == 0x11b)
return -1;
else if (keyCode == 0x1970)
{
BindEvent(_MouseMove,NULL);
BindEvent(_LeftButtonDown,NULL);
BindEvent(_LeftButtonUp,SelectPen);
BindEvent(_RightButtonUp,NULL);
setfillstyle(SOLID_FILL,0);
bar(74-5,224-20,75+29+15*30+1+5,225+29+1+5);
setcolor(15);
rectangle(74-5-1,224-20-1,75+29+15*30+1+5+1,225+29+1+5+1);
outtextxy(74-5+10,224-20+4,"Select the color of your pen ...");
for (i=0;i<16;i++)
{
setfillstyle(SOLID_FILL,i);
bar(75+i*30,225,75+29+i*30,225+29);
}
rectangle(74,224,75+29+15*30+1,225+29+1);
}
return 0;
}
int main()
{
x = -1;
y = -1;
backColor = 8;
penColor = 0;
BindEvent(_FrameOnLoad,OnLoad);
BindEvent(_LeftButtonDown,Start);
BindEvent(_LeftButtonUp,End);
BindEvent(_MouseMove,Draw);
BindEvent(_RightButtonUp,Clear);
BindEvent(_KeyPress,KeyPress);
RunFrame();
}
不光是为了写一个画图,主要是想写一个简单的,但是至少可以扩展,可重用的库,所以,上半部分可以当作一个框架库。使用比较简单的。
/*Some event handle for user.*/
void (*_FrameOnLoad)() = NULL; /*When the frame begin running.*/
void (*_FrameOnClose)() = NULL; /*When the frame close.*/
int (*_MouseMove)(MouseEventArg e) = NULL; /*When the mouse is moving.*/
int (*_LeftButtonDown)(MouseEventArg e) = NULL; /*Just like the name.*/
int (*_LeftButtonUp)(MouseEventArg e) = NULL;
int (*_RightButtonDown)(MouseEventArg e) = NULL;
int (*_RightButtonUp)(MouseEventArg e) = NULL;
int (*_KeyPress)(int keyCode) = NULL;
这些是函数指针,对应相应的事件,可以理解为事件句柄。可以将自己的事件处理函数邦定到事件句柄上,通过BindEvent(handle,proccess)宏可以实现,当然也可以直接等于你的事件处理函数。要注意,事件处理函数的返回类型和参数表中参数数量和参数类型是要和上述指针一致的(学过函数指针应该都知道,呵呵)。
其中有一些事件处理函数有返回值,有些没有。有返回的事件是可以引发程序结束的,只要事件函数返回-1就会使程序结束,返回其他程序会继续。这个画板程序就是在KeyPress事件函数中判断键盘的按键,如果是ESC的话(键码是0x11b)就返回-1,则程序结束。
最后FrameRun函数的调用启动框架的消息循环,程序才开始正式的执行。
用起来还是比较方便的,希望大家喜欢。其中还是存在一些问题的,为了简单起见,就没有去完善她,有待众高手提出意见或修改。
谢谢^_^
[[italic] 本帖最后由 灭火的风 于 2007-12-30 08:48 编辑 [/italic]]