标题:TC下简单的鼠标驱动框架
只看楼主
灭火的风
Rank: 2
来 自:杭州
等 级:论坛游民
帖 子:161
专家分:10
注 册:2006-6-15
 问题点数:0 回复次数:13 
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]]
搜索更多相关主题的帖子: 鼠标 Linux 框架 驱动 画图 
2007-12-30 08:32
灭火的风
Rank: 2
来 自:杭州
等 级:论坛游民
帖 子:161
专家分:10
注 册:2006-6-15
得分:0 
刚才有点问题,现在改好了。
2007-12-30 08:49
xianshizhe111
Rank: 1
等 级:新手上路
帖 子:1451
专家分:0
注 册:2007-12-8
得分:0 
不错,支持一下.
2007-12-30 11:02
死了都要C
Rank: 4
来 自:四川成都
等 级:贵宾
威 望:13
帖 子:1582
专家分:116
注 册:2006-12-7
得分:0 
哎``太强了````

女施主``我给你``送茶来了```师太``你就从了老衲吧``
代码本天成~~~妙头偶得之```
2007-12-30 12:34
sunkaidong
Rank: 4
来 自:南京师范大学
等 级:贵宾
威 望:12
帖 子:4496
专家分:141
注 册:2006-12-28
得分:0 
好强啊.羡慕中...
2007-12-30 13:10
jun0325
Rank: 1
等 级:新手上路
帖 子:37
专家分:0
注 册:2007-8-8
得分:0 
好厉害啊
,高手!我什么时候才有这种水平呢,期待........

数据结构+算法+程序设计方法+语言工具和环境=程序
2007-12-30 13:58
a402711002
Rank: 1
来 自:长春
等 级:新手上路
帖 子:24
专家分:0
注 册:2007-12-7
得分:0 
,看不懂!
  我要好好学习了。。。。
2007-12-30 14:03
永夜的极光
Rank: 6Rank: 6
等 级:贵宾
威 望:27
帖 子:2721
专家分:1
注 册:2007-10-9
得分:0 
不错

从BFS(Breadth First Study)到DFS(Depth First Study)
2007-12-30 14:47
yixiaowz
Rank: 1
等 级:新手上路
帖 子:65
专家分:0
注 册:2007-11-3
得分:0 
厉害啊 ,我还看不懂哦,努力学习先……

2007-12-30 19:22
灭火的风
Rank: 2
来 自:杭州
等 级:论坛游民
帖 子:161
专家分:10
注 册:2006-6-15
得分:0 
其实很简单的,通过函数指针指向事件处理函数
至于鼠标的位置时通过系统调用来实现的,也可以通过内联汇编来系统调用,不过本例是直接用TC里提供的系统调用库函数int86来进行的。
union REGS是一个CPU通用寄存器联合,用来存放CPU通用寄存器里要用到的值。
int86(int interruptCode, union REGS *inputRegs, union REGS *outputRegs)
三个参数分别是中断号,输入寄存器和输出寄存器。这个函数内部的执行过程是这样的:首先将输入寄存器参数的值逐一复制到真正的CPU通用寄存器中,然后执行int指令进行中断调用,等到中断返回在将此时的真实CPU通用寄存器的值都复制到输出寄存器参数中。
获取鼠标位置就是通过这样的系统调用来实现的,鼠标的位置和按键情况都在输出寄存器中。

[[italic] 本帖最后由 灭火的风 于 2008-1-2 18:29 编辑 [/italic]]
2008-01-02 18:25



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-195086-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.021627 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved