📄 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 <g>. 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 <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <memory.h>
#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" );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -