0% found this document useful (0 votes)
120 views

Mouse Programming

This document provides information about mouse programming in C. It discusses loading a mouse driver, initializing the mouse, getting mouse position and button status, restricting mouse movement, and drawing rectangles interactively using the mouse. Key points include initializing the mouse via interrupt 33h, getting mouse data by setting registers and calling interrupt 33h, and using mouse input to draw rectangles by tracking mouse movement and button clicks. Functions like initmouse(), showmouseptr(), restrictmouseptr(), and getmousepos() are used to work with the mouse.

Uploaded by

SAHIDUL ALAM
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
120 views

Mouse Programming

This document provides information about mouse programming in C. It discusses loading a mouse driver, initializing the mouse, getting mouse position and button status, restricting mouse movement, and drawing rectangles interactively using the mouse. Key points include initializing the mouse via interrupt 33h, getting mouse data by setting registers and calling interrupt 33h, and using mouse input to draw rectangles by tracking mouse movement and button clicks. Functions like initmouse(), showmouseptr(), restrictmouseptr(), and getmousepos() are used to work with the mouse.

Uploaded by

SAHIDUL ALAM
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 31

Chapter 21: Mouse Programming

21

Mouse Pro gramming


Drawing With Mouse
Building Mouse Cursors
More Mouse Cursors
Freehand Drawing Using Mouse
Menus Using Mouse
Exercise

155

156

Let Us C

raphical User Interfaces (GUIs) and mouse go hand in


hand. Though some GUIs do exist which manage the
show without a mouse, the mouse has more or less
become a standard input device with any GUI worth its name. A
mouse is used to point at the icons which form the menu in a GUI
much like the way a child points to something he wants.
These point-and-shoot menus of GUI bring along ease and
convenience along with all the added agility of the real-life look
alike of the mouse. As a result, more and more packages today are
not only menu driven, but also mouse driven. The use of a mouse
requires a program to sense its presence. Just attaching the mouse
to the computer is not enough. What we also need to do is load a
device driver program that understands the mouse. A device driver
is a program that senses the signals coming from the port to which
the mouse is attached. On sensing the signals, the driver translates
these into the related action on the screen. This device driver is
usually available as a program called MOUSE.COM, which works
with different variety of mice.
The mouse has a separate cursor (often called a mouse pointer)
which looks like an arrow and functions in the same way as the
normal cursor. As we move the mouse, the mouse pointer moves
correspondingly. It is just like using arrow keys. The only
difference being, the speed at which the mouse cursor moves is
much faster than that of an ordinary cursor. If desired, we can
change the speed of the mouse pointer, and even its shape. Once
the mouse driver is loaded, the various mouse functions can be
accessed by setting up the AX register with different values
(service numbers) and issuing interrupt number 33h. Some of these
functions are used in the following program.
#include "dos.h"
#include "graphics.h"
union REGS i, o ;
main( )

Chapter 21: Mouse Programming


{
int gd = DETECT, gm, maxx, maxy, x, y, button ;
initgraph ( &gd, &gm, "c:\\tc\\bgi" ) ;
maxx = getmaxx( ) ;
maxy = getmaxy( ) ;
rectangle ( 0, 56, maxx, maxy ) ;
setviewport ( 1, 57, maxx - 1, maxy - 1, 1 ) ;
gotoxy ( 26, 1 ) ;
printf ( "Mouse Demonstration Program" ) ;
if ( initmouse( ) == 0 )
{
closegraph( ) ;
restorecrtmode( ) ;
printf ( "\nMouse driver not loaded" ) ;
exit ( 1 ) ;
}
restrictmouseptr ( 1, 57, maxx - 1, maxy - 1 ) ;
showmouseptr( ) ;
gotoxy ( 1, 2 ) ;
printf ( "Left Button" ) ;
gotoxy ( 15, 2 ) ;
printf ( "Right Button" ) ;
gotoxy ( 55, 3 ) ;
printf ( "Press any key to exit... " ) ;
while ( !kbhit( ) )
{
getmousepos ( &button, &x, &y ) ;
gotoxy ( 5, 3 ) ;
( button & 1 ) == 1 ? printf ( "DOWN" ) : printf ( "UP" ) ;

157

Let Us C

158
gotoxy ( 20, 3 ) ;
( button & 2 ) == 2 ? printf ( "DOWN" ) : printf ( "UP" ) ;
gotoxy ( 65, 2 ) ;
printf ( "X = %03d y = %03d", x, y ) ;
}
}
/* initialises mouse */
initmouse( )
{
i.x.ax = 0 ;
int86 ( 0x33, &i, &o ) ;
return ( o.x.ax ) ;
}
/* displays mouse pointer */
showmouseptr( )
{
i.x.ax = 1 ;
int86 ( 0x33, &i, &o ) ;
}
/* restricts mouse movement */
restrictmouseptr ( int x1, int y1, int x2, int y2 )
{
i.x.ax = 7 ;
i.x.cx = x1 ;
i.x.dx = x2 ;
int86 ( 0x33, &i, &o ) ;
i.x.ax = 8 ;
i.x.cx = y1 ;
i.x.dx = y2 ;
int86 ( 0x33, &i, &o ) ;
}

Chapter 21: Mouse Programming

159

/* gets mouse coordinates and button status */


getmousepos ( int *button, int *x, int *y )
{
i.x.ax = 3 ;
int86 ( 0x33, &i, &o ) ;
*button = o.x.bx ;
*x = o.x.cx ;
*y = o.x.dx ;
}

Mouse can be used in text mode as well as in graphics mode.


Usually it is used in graphics mode. Hence we must first change
over to graphics mode. In our program the function initgraph( ) is
responsible for switching the mode from text to graphics.
DETECT is a macro defined in graphics.h. It requests
initgraph( ) to automatically determine which graphics driver to
load in order to switch to the highest resolution graphics mode.
The initgraph( ) function takes three parameters, the graphics
driver, the graphics mode and the path to the driver file.
Once the driver has been loaded, initgraph( ) sets up the numeric
values of the graphics driver and the graphics mode chosen in the
variables gd and gm respectively. Here we are assuming that the
driver files are in the directory c:\tc\bgi. Hence the path passed to
initgraph( ) is c:\\tc\\bgi.
Once we are into the graphics mode we have called the functions
getmaxx( ) and getmaxy( ) to obtain the maximum x and y
coordinates in the current graphics mode. Then we have drawn a
rectangle using the function rectangle( ) and set the view-port area
which restricts any drawing activity within the view-port.
Next we have called the function initmouse( ) to initialize the
mouse. It checks if the mouse driver has been loaded or not (by
issuing interrupt 33h, service number 0) and then reports the status
to main( ). If mouse is not initialized successfully then the

160

Let Us C

closegraph( ) function unloads the graphics driver and


restorecrtmode( ) takes the screen back to the mode that existed
prior to the calling of initgraph( ), which in our case is the text
mode. If you have loaded the mouse driver successfully then in all
probability the mouse would be successfully initialized.
Most softwares today provide windowing feature. Not just
windows on the screen as boxes, but windows that restrict cursor
movement. Like a screen within a screen. If we define the size of
the window then we can make sure that the cursor only moves
within the window. This is what program like Windows or DBMSs
like FoxPro and Access give us. There is nothing too difficult
about it. Its just a matter of putting the right values in the right
registers. In our program this has been achieved by the function
restrictmouseptr( ).
Next,
another
function
called
showmouseptr( ) has been called. It actually displays the mouse
pointer on the screen.
Both the tasks of restricting the mouse pointer movement and
displaying the mouse pointer are achieved by invoking appropriate
services available under interrupt number 33h. In fact once the
mouse driver has been loaded, anything to be done with the mouse
is always done by some service or the other available under
interrupt 33h. Figure 21.1 list some of the important mouse
services, along with values h be set up in CPU registers while
calling them and the values returned by them.

Chapter 21: Mouse Programming

Interrupt
33h

Service
0

33h

33h

33h

33h

33h

33h

Purpose
Reset mouse and get status
Call with: AX = 0
Returns:
AX = FFFFh If mouse support is available
AX = 0 If mouse support is not available
Show mouse pointer
Call with: AX = 1
Returns: Nothing
Hide mouse pointer
Call with: AX = 2
Returns: Nothing
Get mouse position and button status
Call with: AX = 3
Returns: BX = mouse button status
Bit Significance:
0 Left button is down
1 Right button is down
2 Center button is down
CX = x coordinate
DX = y coordinate
Set mouse pointer position
Call with: AX = 4
CX = x coordinate
DX = y coordinate
Returns: Nothing
Set horizontal limits for mouse pointer
Call with: AX = 7
CX = minimum x coordinate
DX = maximum x coordinate
Returns: Nothing
Set vertical limits for mouse pointer
Call with: AX = 8
CX = minimum y coordinate

161

Let Us C

162
DX = maximum y coordinate

Figure 21.1
Then the control enters a while loop where we check to see which
button has been pressed and accordingly display either UP or
DOWN. Additionally, the current coordinates of the mouse
pointer are also displayed. If a key is hit from the keyboard we exit
the loop. Details of some of the more commonly used mouse
services are given on the following page.

Drawing With Mouse


Now that we know how to initialize the mouse, display the mouse
pointer, hide it if required, get the current position of the mouse
cursor and status of the mouse buttons we can put all this to use to
do something worthwhile. Drawing rectangles interactively using
mouse, for example. I have written the following program for a
VGA color monitor in 640 x 480 resolution graphics mode. But it
works even on other monitors with lower resolutions without
making any changes.
#include "graphics.h"
#include "dos.h"
#include "alloc.h"
union REGS i, o ;
int midx, midy ;
char far *p1, far *p2, far *p3, far *p4 ;
main( )
{
int gd = DETECT, gm, button, x, y, sx, sy, tx, ty, x1, y1, x2, y2 ;
if ( initmouse( ) == 0 )
{

Chapter 21: Mouse Programming


printf ( "\nMouse driver not loaded... " ) ;
exit ( 1 ) ;
}
initgraph ( &gd, &gm, "c:\\tc\\bgi" ) ;
gotoxy ( 1, 1 ) ;
printf ( "Draw box..... " ) ;
gotoxy ( 60, 1 ) ;
printf ( "Right button to exit" ) ;
do
{
showmouseptr( ) ;
getmousepos ( &button, &tx, &ty ) ;
if ( button & 1 == 1 )
{
hidemouseptr( ) ;
sx = x = x1 = x2 = tx ;
sy = y = y1 = y2 = ty ;
setcolor ( WHITE ) ;
save ( x1, y1, x2, y2 ) ;
rectangle ( x1, y1, x2, y2 ) ;
getmousepos ( &button, &tx, &ty ) ;
while ( ( button & 1 ) == 1 )
{
if ( x != tx || y != ty )
{
setcolor ( BLACK ) ;
rectangle ( x1, y1, x2, y2 ) ;
restore ( x1, y1 ) ;
x = tx ;
y = ty ;
if ( x < sx )
{
x1 = x ;

163

Let Us C

164
x2 = sx ;
}
else
{
x1 = sx ;
x2 = x ;
}
if ( y < sy )
{
y1 = y ;
y2 = sy ;
}
else
{
y1 = sy ;
y2 = y ;
}
setcolor ( WHITE ) ;
save ( x1, y1, x2, y2 ) ;
rectangle ( x1, y1, x2, y2 ) ;
}
getmousepos ( &button, &tx, &ty ) ;
}
restore ( x1, y1 ) ;
showmouseptr( ) ;
}
} while ( ( button & 2 ) != 2 ) ;
gotoxy ( 1, 1 ) ;
printf ( "Press any key to exit" ) ;
gotoxy ( 60, 1 ) ;
printf ( " " ) ;
getch( ) ;

Chapter 21: Mouse Programming


closegraph( ) ;
}
save ( int x1, int y1, int x2, int y2 )
{
unsigned area1, area2, area3, area4 ;
midx = x1 + (x2 - x1) / 2 ;
midy = y1 + (y2 - y1) / 2 ;
area1 = imagesize ( x1, y1, midx, midy ) ;
p1 = farmalloc ( area1 ) ;
area2 = imagesize ( midx + 1, y1, x2, midy ) ;
p2 = farmalloc ( area2 ) ;
area3 = imagesize ( x1, midy + 1, midx, y2 ) ;
p3 = farmalloc ( area3 ) ;
area4 = imagesize ( midx + 1, midy + 1, x2, y2 ) ;
p4 = farmalloc ( area4 ) ;
if ( p1 == NULL || p2 == NULL || p3 == NULL || p4 == NULL )
{
closegraph( ) ;
printf ( Memory allocation error! ) ;
exit ( 2 ) ;
}
getimage ( x1, y1, midx, midy, p1 ) ;
getimage ( midx + 1, y1, x2, midy, p2 ) ;
getimage ( x1, midy + 1, midx, y2, p3 ) ;
getimage ( midx + 1, midy + 1, x2, y2, p4 ) ;
}
restore ( int x1, int y1 )
{
putimage ( x1, y1, p1, OR_PUT ) ;
putimage ( midx + 1, y1, p2, OR_PUT ) ;
putimage ( x1, midy + 1, p3, OR_PUT ) ;

165

166
putimage ( midx + 1, midy + 1, p4, OR_PUT ) ;
farfree ( p1 ) ;
farfree ( p2 ) ;
farfree ( p3 ) ;
farfree ( p4 ) ;
}
initmouse( )
{
i.x.ax = 0 ;
int86 ( 0x33, &i, &o ) ;
return ( o.x.ax ) ;
}
showmouseptr( )
{
i.x.ax = 1 ;
int86 ( 0x33, &i, &o ) ;
}
hidemouseptr( )
{
i.x.ax = 2 ;
int86 ( 0x33, &i, &o ) ;
}
restrictmouseptr ( int x1, int y1, int x2, int y2 )
{
i.x.ax = 7 ;
i.x.cx = x1 ;
i.x.dx = x2 ;
int86 ( 0x33, &i, &o ) ;
i.x.ax = 8 ;
i.x.cx = y1 ;
i.x.dx = y2 ;
int86 ( 0x33, &i, &o ) ;

Let Us C

Chapter 21: Mouse Programming

167

}
getmousepos ( int *button, int *x, int *y )
{
i.x.ax = 3 ;
int86 ( 0x33, &i, &o ) ;
*button = o.x.bx ;
*x = o.x.cx ;
*y = o.x.dx ;
}

Building Mouse Cursors


In text mode the mouse cursor appears as a block, whereas in
graphics mode it appears as an arrow. If we wish, we can change
the graphics cursor to any other shape the way Windows or other
software do. The mouse cursor in graphics mode occupies a 16 by
16 pixel box. By highlighting or de-highlighting some of the pixels
in this box we can get a mouse cursor of the desired shape. For
example, the bit-pattern shown in Figure 21.2 can be used to
generate the cursor that looks like an hourglass.
The 1s in the mouse pointer bitmap indicate that the pixel would
be drawn, whereas the zeros indicate that the pixel would stand
erased. It is important to note that though the mouse pointer bit
pattern is 32 bytes long, while actually writing a program to
change the pointer shape we need a 64-byte bitmap. This is done to
ensure that when the cursor reaches a position on the screen where
something is already written or drawn, only that portion gets
overwritten which is going to be occupied by the mouse cursor. Of
the 64 bytes, the first 32 bytes contain a bit mask which is first
ANDed with the screen image, and then the second 32 bytes bit
mask is XORed with the screen image. The following program
changes the mouse cursor in graphics mode to resemble an
hourglass.

Let Us C

168

1111111111111111

0000000000000000

1000000000000001

0000000000000000

1111111111111111

0000000000000000

1000000000000001

0000000000000000

0100000000000010

1000000000000001

0010000000000100

1100000000000011

0000100000010000

1111000000001111

0000001001000000

1111110000111111

0000001001000000

1111110000111111

0000100000010000

1111000000001111

0010000000000100

1100000000000011

0100000000000010

1000000000000001

1000000000000001

0000000000000000

1111111111111111

0000000000000000

1000000000000001

0000000000000000

1111111111111111

0000000000000000

Mouse pointer bitmap

Screen Mask

Figure 21.2
#include "graphics.h"

Chapter 21: Mouse Programming


#include "dos.h"
union REGS i, o ;
struct SREGS s ;
int cursor[32] = {
/* hour-glass screen mask */
0x0000, 0x0000, 0x0000, 0x0000,
0x8001, 0xc003, 0xf00f, 0xfc3f,
0xfc3f, 0xf00f, 0xc003, 0x8001,
0x0000, 0x0000, 0x0000, 0x0000,
/* the mouse pointer bitmap */
0xffff, 0x8001, 0xffff, 0x8001,
0x4002, 0x2004, 0x1008, 0x0240,
0x0240, 0x0810, 0x2004, 0x4002,
0x8001, 0xffff, 0x8001, 0xffff
};
main( )
{
int gd = DETECT, gm ;
initgraph ( &gd, &gm, "c:\\tc\\bgi" ) ;
if ( initmouse( ) == 0 )
{
closegraph( ) ;
printf ( "\n Mouse not installed!" ) ;
exit ( 1 ) ;
}
gotoxy ( 10, 1 ) ;
printf ( "Press any key to exit..." ) ;
changecursor ( cursor ) ;
showmouseptr( ) ;
getch( ) ;

169

170

Let Us C

}
initmouse( )
{
i.x.ax = 0 ;
int86 ( 0x33, &i, &o ) ;
return ( o.x.ax ) ;
}
showmouseptr( )
{
i.x.ax = 1 ;
int86 ( 0x33, &i, &o ) ;
}
changecursor ( int *shape )
{
i.x.ax = 9 ; /* service number */
i.x.bx = 0 ; /* actual cursor position from left */
i.x.cx = 0 ; /* actual cursor position from top */
i.x.dx = ( unsigned ) shape ; /* offset address of pointer image */
segread ( &s ) ;
s.es = s.ds ; /* segment address of pointer */
int86x ( 0x33, &i, &i, &s ) ;
}

More Mouse Cursors


In the last program we saw how to change the default mouse
cursor. Once we know this we can think of building different
shapes of mouse cursors, each to signify a different operation or
mode. This is done by many software to show in which mode (edit
mode, drawing mode, etc.) are we working currently. The
following program shows how this can be managed.
The functions initmouse( ), changecursor( ), showmouseptr( ),
getmousepos( ), hidemouseptr( ) which have been discussed in
the last three programs have not been reproduced here.

Chapter 21: Mouse Programming


# include "graphics.h"
# include "dos.h"
#include "alloc.h"
union REGS i, o ;
struct SREGS s ;
int c[ ][32] = {
/* Cursor 1. Hand-screen mask + pointer bit map */
0xe1ff, 0xe1ff, 0xe1ff, 0xe1ff, 0xe1ff, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x1e00, 0x1200,
0x1200, 0x1200, 0x13ff, 0x1249, 0x1249, 0xf249,
0x9001, 0x9001, 0x9001, 0x8001, 0x8001, 0x8001,
0xffff, 0x0000,
/* Cursor 2. Arrow-screen mask + pointer bit map */
0xffff, 0xffff, 0xe003, 0xf003, 0xf803, 0xfc03,
0xfe03, 0xfc03, 0xf803, 0xf043, 0xe0e3, 0xc1f3,
0x83fb, 0x07ff, 0x8fff, 0xdfff, 0x0000, 0x0000,
0x1ffc, 0x0804, 0x0404, 0x0204, 0x0104, 0x0204,
0x0444, 0x08a4, 0x1114, 0x220c, 0x4404, 0x8800,
0x5000, 0x2000,
/* Cursor 3. Hour glass mask + bit map */
0x0000, 0x0000, 0x0000, 0x0000, 0x8001, 0xc003,
0xf00f, 0xfc3f, 0xfc3f, 0xf00f, 0xc003, 0x8001,
0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x8001,
0xffff, 0x8001, 0x4002, 0x2004, 0x1008, 0x0240,
0x0240, 0x0810, 0x2004, 0x4002, 0x8001, 0xffff,
0x8001, 0xffff,
/* Cursor 4. Para-screen mask + pointer bit map */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff,
0xffff, 0x0007, 0x0007, 0xeee7, 0x0007, 0x0007,

171

Let Us C

172

0xeee7, 0x0007, 0x0007, 0xeee7, 0x0007, 0x0007,


0xeee7, 0xeee7
};
main( )
{
int gd = DETECT, gm, button, x, y, area, i, choice ;
char *p ;
initgraph ( &gd, &gm, "c:\\tc\\bgi" ) ;
if ( initmouse( ) == 0 )
{
closegraph( ) ;
puts ( "Mouse not installed!" ) ;
exit ( 1 ) ;
}
for ( i = 0 ; i < 4 ; i++ )
{
changecursor ( c[i] ) ;
showmouseptr( ) ;
getmousepos ( &button, &x, &y ) ;
area = imagesize ( x - 15, y - 7, x + 32, y + 24 ) ;
p = malloc ( area ) ;
getimage ( x - 15, y - 7, x + 32, y + 24, p ) ;
putimage ( i * 48 + 1, 1, p, COPY_PUT ) ;
rectangle ( i * 48, 0, ( i + 1 ) * 48, 33 ) ;
}
gotoxy ( 10, 25 ) ;
printf ( "Press any key to exit... " ) ;
choice = 1 ;
disp ( choice, p ) ;
changecursor ( c[choice - 1] ) ;
while ( !kbhit( ) )

Chapter 21: Mouse Programming


{
getmousepos ( &button, &x, &y ) ;
if ( ( button & 1 ) == 1 )
{
for ( i = 0 ; i < 4 ; i++ )
{
if ( choice - 1 == i )
continue ;
if ( y > 0 && y < 33 )
{
if ( x > i * 48 && x < ( i + 1 ) * 48 )
{
hidemouseptr( ) ;
disp ( choice, p ) ;
choice = i + 1 ;
disp ( choice, p ) ;
changecursor ( c[choice - 1] ) ;
showmouseptr( ) ;
}
}
}
}
}
getch( ) ;
}
disp ( int choice, char *p )
{
getimage ( ( choice - 1 ) * 48 + 1, 1, choice * 48, 32, p ) ;
putimage ( ( choice - 1 ) * 48 + 1, 1, p, NOT_PUT ) ;
}

Freehand Drawing Using Mouse

173

174

Let Us C

Let us now try to gather all that we know about the mouse and its
functions to develop a utility for drawing freehand... the way it is
done in softwares like Paintbrush, Corel Draw etc. Here is the
program...
#include "dos.h"
#include "graphics.h"
union REGS i, o ;
main( )
{
int gd = DETECT, gm, maxx, maxy, x, y, button, prevx, prevy ;
initgraph ( &gd, &gm, "c:\\tc\\bgi" ) ;
maxx = getmaxx( ) ;
maxy = getmaxy( ) ;
rectangle ( 0, 0, maxx, maxy ) ;
setviewport ( 1, 1, maxx - 1, maxy - 1, 1 ) ;
if ( initmouse( ) == 0 )
{
closegraph( ) ;
restorecrtmode( ) ;
printf ( "Mouse driver not loaded" ) ;
exit ( 1 ) ;
}
restrictmouseptr ( 1, 1, maxx - 1, maxy - 1 ) ;
showmouseptr( ) ;
while ( !kbhit( ) )
{
getmousepos ( &button, &x, &y ) ;
if ( ( button & 1 ) == 1 )
{

Chapter 21: Mouse Programming


hidemouseptr( ) ;
prevx = x ;
prevy = y ;
while ( ( button & 1 ) == 1 )
{
line ( prevx, prevy, x, y ) ;
prevx = x ;
prevy = y ;
getmousepos ( &button, &x, &y ) ;
}
showmouseptr( ) ;
}
}
}
initmouse( )
{
i.x.ax = 0 ;
int86 ( 0x33, &i, &o ) ;
return ( o.x.ax )
}
showmouseptr( )
{
i.x.ax = 1 ;
int86 ( 0x33, &i, &o ) ;
}
hidemouseptr( )
{
i.x.ax = 2 ;
int86 ( 0x33, &i, &o ) ;
}
restrictmouseptr ( int x1, int y1, int x2, int y2 )

175

176

Let Us C

{
i.x.ax = 7 ;
i.x.cx = x1 ;
i.x.dx = x2 ;
int86 ( 0x33, &i, &o ) ;
i.x.ax = 8 ;
i.x.cx = y1 ;
i.x.dx = y2 ;
int86 ( 0x33, &i, &o ) ;
}
getmousepos ( int *button, int *x, int *y )
{
i.x.ax = 3 ;
int86 ( 0x33, &i, &o ) ;
*button = o.x.bx ;
*x = o.x.cx ;
*y = o.x.dx ;
}

In main( ) the loop while ( !kbhit( ) ) allows the drawing of as


many freehand drawings as the user desires, the process stopping
when the user hits a key from the keyboard. The freehand drawing
begins on hitting the left mouse button, and grows as the mouse is
dragged with the left button depressed. On releasing the left button
the freehand drawing is terminated. When the actual drawing is in
progress the mouse pointer is hidden, and it reappears when the
mouse button is released.

Menus Using Mouse


So often do we navigate within menus of best-selling softwares
using mouse that we do not think for a moment how these menus
are developed. The following program shows how such programs
can be written. Care has been taken to ensure that the menu would

Chapter 21: Mouse Programming

177

work for all memory models and for different types of adapters
like CGA, EGA, VGA etc.
#include "dos.h"
#include "graphics.h"
#include "alloc.h"
char *menu[ ] = { "Samosa", "Sambarwada", "Dahiwada", "Exit" } ;
union REGS i, o ;
main( )
{
int gd = DETECT, gm, choice = 1, bill = 0, width = 0, i, count ;
char **buffer ;
initgraph ( &gd, &gm, "c:\\tc\\bgi" ) ;
if ( initmouse( ) == 0 )
{
printf ( "\nUnable to initialise Mouse... " ) ;
exit( ) ;
}
count = sizeof ( menu ) / sizeof ( char * ) ;
settextstyle ( TRIPLEX_FONT, 0, 3 ) ;
displaymenu ( menu, count, 100, 100 ) ;
for ( i = 0 ; i < count ; i++ )
{
if ( textwidth ( menu[i] ) > width )
width = textwidth ( menu[i] ) ;
}
buffer = malloc ( sizeof ( menu ) ) ;
savemenu ( menu, buffer, width, count, 100, 100 ) ;
while ( choice != 4 )

Let Us C

178
{

choice = getresponse ( menu, buffer, width, count, 100, 100 ) ;


gotoxy ( 50, 15 ) ;
printf ( "You selected %s ", menu[choice - 1] ) ;
}
}
displaymenu ( char **menu, int count, int x1, int y1 )
{
int i, h ;
h = textheight ( menu[0] ) ;
for ( i = 0 ; i < count ; i++ )
outtextxy ( x1, y1 + i * ( h + 5 ), menu[i] ) ;
}
savemenu ( char **menu, char **buffer, int width, int count, int x1, int y1 )
{
int i, x2, yy1, yy2, area, h ;
h = textheight ( menu[0] ) ;
for ( i = 0 ; i < count ; i++ )
{
x2 = x1 + width ;
yy1 = y1 + i * ( h + 5 ) ;
yy2 = y1 + ( i + 1 ) * ( h + 5 ) ;
area = imagesize ( x1, yy1, x2, yy2 ) ;
buffer[i] = malloc ( area ) ;
getimage ( x1, yy1, x2, yy2, buffer[i] ) ;
}
}
getresponse ( char **menu, char **buffer, int width, int count, int x1,
int y1 )

Chapter 21: Mouse Programming


{
int choice = 1, prevchoice = 0, x, y, x2, y2, button ;
int in, i, h ;
h = textheight ( menu[0] ) ;
y2 = y1 + count * ( h + 5 ) ;
x2 = x1 + width ;
rectangle ( x1 - 5, y1 - 5, x2 + 5, y2 + 5 ) ;
while ( 1 )
{
getmousepos ( &button, &x, &y ) ;
if ( x >= x1 && x <= x2 && y >= y1 && y <= y2 )
{
in = 1 ;
for ( i = 1 ; i <= count ; i++ )
{
if ( y <= y1 + i * ( h + 5 ) )
{
choice = i ;
break ;
}
}
if ( prevchoice != choice )
{
hidemouseptr( ) ;
highlight ( buffer, choice, h, x1, y1 ) ;
if ( prevchoice )
dehighlight ( buffer, prevchoice, h, x1, y1 ) ;
prevchoice = choice ;
showmouseptr( ) ;
}

179

Let Us C

180
if ( ( button & 1 ) == 1 )
{
while ( ( button & 1 ) == 1 )
getmousepos ( &button, &x, &y ) ;

if ( x >= x1 && x <= x2 && y >= y1 && y <= y2 )


return ( choice ) ;
}
}
else
{
if ( in == 1 )
{
in = 0 ;
prevchoice = 0 ;
hidemouseptr( ) ;
dehighlight ( buffer, choice, h, x1, y1 ) ;
showmouseptr( ) ;
}
}
}
}
highlight ( char **buffer, int ch, int h, int x1, int y1 )
{
putimage( x1, y1 + ( ch - 1 ) * ( h + 5 ), buffer[ch - 1], NOT_PUT ) ;
}
dehighlight ( char **buffer, int ch, int h, int x1, int y1 )
{
putimage( x1, y1 + ( ch - 1 ) * ( h + 5 ), buffer[ch - 1], COPY_PUT ) ;
}
initmouse( )
{
i.x.ax = 0 ;

Chapter 21: Mouse Programming

181

int86 ( 0x33, &i, &o ) ;


return ( o.x.ax )
}
showmouseptr( )
{
i.x.ax = 1 ;
int86 ( 0x33, &i, &o ) ;
}
hidemouseptr( )
{
i.x.ax = 2 ;
int86 ( 0x33, &i, &o ) ;
}
getmousepos ( int *button, int *x, int *y )
{
i.x.ax = 3 ;
int86 ( 0x33, &i, &o ) ;
*button = o.x.bx ;
*x = o.x.cx ;
*y = o.x.dx ;
}

Note that the menu items are stored in an array of pointers to


strings menu[ ]. Once the graphics system and the mouse has been
initialized, the number of items in the menu are determined, text
style is set and the menu is displayed on the screen using the
function displaymenu( ). To highlight or de-highlight the menu
items, rather than building the items from scratch their existing
images are stored in a buffer.
The space for this buffer is allocated using malloc( ) and the actual
saving of images is done through the function savemenu( ). The
base addresses of these images are stored in an array of pointers,
pointed to by the variable buffer. Using these addresses let us now

182

Let Us C

see how do we go about moving the highlighted bar using mouse


and then make a selection from the menu by clicking on the left
mouse button. All this is achieved by the function getresponse( ).
To begin with, the getresponse( ) function checks the position of
the mouse pointer. If the mouse pointer is inside the area occupied
by the menu then it checks on which menu item is it placed and
highlights that item. If the user attempts to move the mouse pointer
outside this menu item then it is de-highlighted. If an item is
highlighted and the left mouse button is clicked then it is assumed
that the menu item has been selected and an appropriate value is
returned. Observe that, to highlight an item, the putimage( )
function has been used in such a manner that the existing image of
the item is just reversed.

Exercise
[A] State True or False:

(a) All mouse services have been gather under interrupt number
51.
(b) It is possible to build mouse pointer in graphics mode of size
bigger then 16x16 pixel.
(c) It is mandatory that the mouse driver should stand loaded
before we can use the mouse.
(d) We can build the arrow shape mouse pointer in text mode.
(e) We can build a color mouse pointer through interrupt number
33h.
(f) To find out the status of the different mouse buttons, we have
to use different services under interrupt number 33h.
(g) The service to initialize the mouse also manages to display the
mouse pointer.

Chapter 21: Mouse Programming

183

(h) Once the mouse pointer is displayed, we need to call another


service under interrupt number 33h to make the mouse pointer
move.
(i) There exist different services to obtain the current mouse
position and the status of different mouse buttons.
(j) In any mouse pointer built from 16x16 pixel matrix, the top
left pixel is considered to signify the actual mouse position.
[B] Answer the following:

(a) Write a function that would not allow the mouse pointer to
enter a particular rectangular area on the screen. Use the
following details:
Interrupt number 33h
AX 16, service to deactivate mouse when it enters rectangle defined
by CX, DX, SI, DI
CX upper X screen coordinate
DX upper Y screen coordinate
SI lower X screen coordinate
DI lower Y screen coordinate
(b) Write a function that allows a user to set the sensitivity of the
mouse. The sensitivity is measured in a unit called mickeys
where 1 mickey represents approximately 1 / 200 of an inch
of mouse travel on the table. Effectively it means how much
movement of the mouse on the table would cause the mouse
cursor to move by one unit on the screen, where one unit
corresponds to 8 pixels. Use the following details:
Interrupt number 33h
AX 1Ah
BX = horizontal mickeys (1 to 32767, default = 8)
CX = vertical mickeys (1 to 32767, default = 16)

184

Let Us C

Chapter 21: Mouse Programming

185

You might also like