www.pudn.com > msesrc > MOUSE.C


/*====================================================================*/ 
/*                                                                    */ 
/*  NOTE: Ensure this program is compiled for LARGE model.            */ 
/*        Non-ANSI stuff is pertinent to Microsoft QuickC v2.5.       */ 
/*        Porting to another compiler should not be too hard!         */ 
/*                                                                    */ 
/*====================================================================*/ 
 
/*  What we are going to demonstrate here is the use of the mouse in    */ 
/*  video modes 0x13 (320x200x256) and 0x12 (640x480x16). In both we    */ 
/*  will simply display some text and allow the mouse to be moved. As   */ 
/*  the buttons are pressed and the mouse moved we will display the     */ 
/*  mouse position and button status. Use of the mouse is very simple   */ 
/*  as long as you obey certain rules:                                  */ 
/*                                                                      */ 
/*  1. Never draw to the screen when the mouse cursor is on. Always     */ 
/*     turn the mouse off before any drawing.                           */ 
/*  2. MouseOn() and MouseOff() are cummulative - i.e. 2 MouseOff()s    */ 
/*     will require 2 MouseOn()s before the cursor is visible again.    */ 
/*     However, once the mouse is on, many MouseOn()s will only require */ 
/*     one MouseOff() to make the cursor invisible.                     */ 
/*  3. Even if the cursor is off, the mouse is still 'working' and can  */ 
/*     be interrogated with MouseStatus().                              */ 
/*  4. For some strange reason, when 320x200x256 mode is on the x value */ 
/*     returned by the mouse driver needs to be divided by 2 (shifted   */ 
/*     right 1) to convert to actual screen pixel coordinates.          */ 
/*  5. If the video mode is changed, the mouse cursor is forced off.    */ 
/*                                                                      */ 
/*  As a final example, we will implement a third test that turns the   */ 
/*  mouse cursor off and simply tracks the cursor position so we can    */ 
/*  implement our OWN cursor. In this case, it will be just cross-hair  */ 
/*  type cursor. This last demo is only to demonstrate one method of    */ 
/*  implementing a cursor. What it doesn't do is actually do the job    */ 
/*  properly . A true cursor would store a copy of what was being    */ 
/*  overwritten on screen so that it could be restored once the cursor  */ 
/*  has moved. This is highlighted by the fact that, 'cos the cursor is */ 
/*  alternately drawn in black and white, why it is possible to 'clear' */ 
/*  the text at the top of the screen. Any true cursor implementation   */ 
/*  should handle this problem which is easy to do     in mode 0x13 but */ 
/*  it's harder to deal with in mode 0x12 which is planar rather than   */ 
/*  linear. I'll leave that to you 'cos I can't be asked to do it now!  */ 
 
#include  
#include  
#include  
#include  
#include  
 
#define FALSE         0 
#define TRUE          1 
 
typedef unsigned char BOOL; 
typedef unsigned char BYTE; 
typedef unsigned int  WORD; 
 
/*=========================== Simple Support Functions ======================*/ 
 
BYTE    *pVideo=(BYTE *)0xA0000000L;       /*  Ptr to base of VGA video RAM  */ 
 
#define BLACK       0       /*  Colours from the std VGA palette  */ 
#define WHITE       15 
 
void SetVideoMode( int nMode ) 
{ 
    /*  Simple routine to set the video mode using the BIOS video interrupt  */ 
 
    _asm    mov ah, 00H 
    _asm    mov al, byte ptr nMode 
    _asm    int 10H 
} 
 
void SetPixel( int x, int y, int colour ) 
{ 
    /*  Very simple (inefficient) way of setting a pixel colour  */ 
 
    *(pVideo+(unsigned)y*320U+(unsigned)x) = (BYTE)colour; 
} 
 
void DrawCross( int cx, int cy, int colour ) 
{ 
    /*  Simple function to draw a 'cross-hair' cursor.  */ 
 
#define XWTH    4       /*  Aspect ration in 320x200 is approx 3/4  */ 
#define YHT     3 
 
    int     x, y; 
 
    if ( cx>=0 && cx<320 ) 
    { 
        for ( y=cy-YHT; y<=cy+YHT; y++ ) 
        { 
            if ( y>=0 && y<200 ) SetPixel( cx,y,colour ); 
        } 
    } 
 
    if ( cy>=0 && cy<200 ) 
    { 
        for ( x=cx-XWTH; x<=cx+XWTH; x++ ) 
        { 
            if ( x>=0 && x<320 ) SetPixel(x,cy,colour); 
        } 
    } 
} 
 
void SetCursorPos( int col, int row ) 
{ 
    /*  Even though we will be in graphics mode we can ask the video BIOS  */ 
    /*  to set our cursor position for displaying text...                  */ 
 
    _asm    mov ah, 02H 
    _asm    mov bh, 00H 
    _asm    mov dl, byte ptr col 
    _asm    mov dh, byte ptr row 
    _asm    int 10H 
} 
 
/*============================= Mouse Routines ==============================*/ 
 
#define   MOUSE_INT     0x33 
#define   L_BUTTON      0x01 
#define   R_BUTTON      0x02 
 
BOOL CheckMouse( void ) 
{ 
    /*  Checks to see if mouse/driver is present. Returns TRUE if found  */ 
 
    /*  TIP: Don't repeatedly call this function within your programs.   */ 
    /*  call it only once and assign it to your own flag. When the mouse */ 
    /*  driver receives this function call it does some time consuming   */ 
    /*  initialisation stuff. If you watch this program carefully when   */ 
    /*  you run it you'll notice a slight pause...                       */ 
 
    int     aa; 
 
    _asm  mov    ax, 0000H 
    _asm  int    MOUSE_INT 
    _asm  mov    aa, ax 
 
    return( (aa!=0?TRUE:FALSE) ); 
} 
 
int MouseStatus( int *buttons, int *xpos, int *ypos ) 
{ 
    /*  Returns buttons pressed or 0  */ 
 
    int     x, y, b; 
 
    _asm    mov    ax, 0003H 
    _asm    int    MOUSE_INT 
    _asm    and    bx, 03H 
    _asm    mov    b,  bx 
    _asm    mov    x,  cx 
    _asm    mov    y,  dx 
 
    *buttons = b; 
    *xpos    = x; 
    *ypos    = y; 
 
    return( b ); 
} 
 
void MouseOn( void ) 
{ 
    /*  Turn on the mouse cursor  */ 
 
    _asm    mov    ax, 0001H 
    _asm    int    MOUSE_INT 
} 
 
void MouseOff( void ) 
{ 
    /*  Turns the mouse cursor off  */ 
 
    _asm    mov    ax, 0002H 
    _asm    int    MOUSE_INT 
} 
 
void SetMousePos( int x, int y ) 
{ 
    /*  Set the position of the mouse cursor  */ 
 
    _asm    mov    ax, 0004H 
    _asm    mov    cx, x 
    _asm    mov    dx, y 
    _asm    int    MOUSE_INT 
} 
 
/*========================= main program ====================================*/ 
 
void main( void ) 
{ 
    int     nDemo, x, y, b, lx, ly, lb, maxx, maxy, key; 
    BOOL    bAbort=FALSE; 
    char    szBuffer[32]; 
 
    printf( "\n\nMouse Demo\n==========\n\nPress ESCape to abort at any time.\nPress A Key..." ); 
    if ( getch()==27 ) exit( 1 ); 
 
    /*  Check for presence of mouse driver  */ 
 
    if ( !CheckMouse() ) 
    { 
        printf( "\n\nSorry, you'll need a rodent for this!\n\n" ); 
        exit( 1 ); 
    } 
 
    for ( nDemo=0; nDemo<3 && !bAbort; nDemo++ ) 
    { 
        /*  Initialise items for this demo  */ 
 
        if ( nDemo==0 || nDemo==2 ) 
        { 
            /*  Initialise stuff for 320x200x256  */ 
 
            SetVideoMode( 0x13 ); 
            maxx = 320; 
            maxy = 200; 
        } 
        else 
        { 
            SetVideoMode( 0x12 ); 
            maxx = 640; 
            maxy = 480; 
        } 
 
        /*  At this point the mouse will be off. We are safe to draw some stuff  */ 
 
        SetCursorPos( 0,0 ); 
        printf( "Press ESC to quit or N for next" ); 
 
        /*  Initialise our mouse so that it will be in the middle of the  */ 
        /*  screen and set last position indicators to cut down on redraw */ 
        /*  flicker...                                                    */ 
 
        x   = maxx/2; 
        y   = maxy/2; 
        b   = 0; 
        lx  = -1; 
        ly  = -1; 
        lb  = 0; 
 
        if ( maxx==320 ) x*=2;      /*  320x200 needs to have x doubled  */ 
        SetMousePos( x,y ); 
 
        /*  Okay, turn on the rodent unless we are going to use our OWN... */ 
 
        if ( nDemo!=2 ) MouseOn(); 
 
        while ( 1 )         /*  Keep on loopin...  */ 
        { 
            /*  Look for a getout  */ 
 
            key=0; 
            if ( kbhit() && (key=getch())==27 ) 
            { 
                bAbort = TRUE; 
                break; 
            } 
 
            /*  Next demo...  */ 
 
            if ( key=='n' || key=='N' ) break; 
 
            /*  Get the mouse position and status, etc...  */ 
 
            MouseStatus( &b,&x,&y ); 
 
            /*  If in 320x200 mode, the x coordinate needs to be divided by 2  */ 
 
            if ( maxx==320 ) x/=2; 
 
            /*  See if something has changed  */ 
 
            if ( lx!=x || ly!=y ) 
            { 
                /*  Update the position counter  */ 
 
                sprintf( szBuffer,"%3d,%3d",x,y ); 
                if ( nDemo==2 )         /*  Our OWN mouse...         */ 
                { 
                    /*  Remove last cursor  */ 
 
                    if ( lx!=-1 ) DrawCross( lx,ly,BLACK ); 
                } 
                else 
                { 
                    MouseOff();         /*  Make sure not on screen  */ 
                } 
                SetCursorPos( 0,1 ); 
                printf( szBuffer ); 
                if ( nDemo==2 )         /*  Our OWN mouse...          */ 
                { 
                    /*  Draw at new position  */ 
 
                    DrawCross( x,y,WHITE ); 
                } 
                else 
                { 
                    MouseOn();          /*  Okay, all drawing done... */ 
                } 
                lx = x; 
                ly = y; 
            } 
 
            if ( b!=lb ) 
            { 
                /*  Update the button indicators  */ 
 
                if ( (b&L_BUTTON) != (lb&L_BUTTON) ) 
                { 
                    MouseOff(); 
                    SetCursorPos( 0,3 ); 
                    printf( "%2s",(b&L_BUTTON?"B1":"") ); 
                    MouseOn(); 
                } 
                if ( (b&R_BUTTON) != (lb&R_BUTTON) ) 
                { 
                    MouseOff(); 
                    SetCursorPos( 4,3 ); 
                    printf( "%2s",(b&R_BUTTON?"B2":"") ); 
                    MouseOn(); 
                } 
                lb = b; 
            } 
        } 
 
        /*  Turn mouse off for completeness  */ 
 
        MouseOff(); 
    } 
 
    SetVideoMode( 0x03 ); 
 
    printf( "\n\nMouse Demo Coded by CyberFrog 8:)\n\n" ); 
}