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" ); }