⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mouse.doc

📁 这是一个C++编程文档
💻 DOC
📖 第 1 页 / 共 4 页
字号:

                          Mouse++ Version 4.0

                  Copyright (c)1992 by Carl Moreland
                               10/06/92

-----------------------------------------------------------------------

Using the Mouse Class

    To  incorporate  the  mouse routines in your  program,  simply  add
mouse.lib to your project or make file and #include mouse.h in any  mo-
dule that calls a mouse function.  mouse.lib contains all the functions
in mouse.cpp and cgc.cpp,  but the functions are separated into differ-
ent object modules for greater efficiency.  Note that mouse.lib is com-
piled for the large memory model.

    An instance of the Mouse class (there can only be ONE instance)  is 
declared as extern in mouse.h,  so any file that #includes mouse.h will 
automatically have access to the mouse.  You should NOT declare an  in-
stance of the Mouse class in any part of your program. If you intend to
change the mouse cursor, then you also need to #include cursor.h.

    When you link the mouse code into your program,  an instance of the
mouse class is declared:

	Mouse mouse;

The  constructor Mouse::Mouse() calls the mouse driver  reset  function
(all mouse driver functions are called via interrupt 33h)  and  initia-
lizes  the flags exists, enabled, and visible.  exists is set to 1 if a
mouse  was  found and should be checked first.  All other  mouse  class
functions check exists before issuing interrupt 33h calls and abort  if
it  is zero.  enabled is initially zero meaning the mouse is  disabled,
and  visible is used by Show() and Hide() to keep track of  the  cursor
visibility. An example of initializing the mouse is:

	#include "mouse.h"

	main()
	{
	  if(mouse.Exists())		// check for mouse
	  {
	    mouse.Enable();		// enable the mouse
	    mouse.Show();		// display the cursor
	    ...
	  }
	}

Again,  including  mouse.h automatically creates  an  instance  of  the
class, so all you have to do is start using it.

    Once  the  mouse is initialized,  it may be necessary to  set  some
parameters based on what video mode is being used. Strangely, the mouse
driver  uses  pixel coordinates for both text and graphics  mode,  with
(0,0)  being  the upper left hand corner of the screen,  and  (639,199)
being  the default lower right hand corner.  This would be correct  for
CGA graphics mode and for normal 80x25 text mode - for text mode,  this
means that each character cell is treated as an 8x8 pixel array. If you
are programming for the EGA or VGA as is the norm these days,  you will
want  to change the y-limit of 199 for high resolution graphics and  43
or 50 line text modes.  Failure to do this means that the mouse  cursor
will not move below the 200th line in graphics mode, or the 25th row in
text mode.  (Older mouse drivers might not support more than 200 lines.
If  this is the case,  you will need to update your mouse driver.)  For
640x480 VGA graphics, you need to set the y-limit to (0,479) by calling
yLimit(0,479).  For  43 or 50 line text mode,  the mouse  driver  still
treats  each character cell as an 8x8 pixel array,  so you need to  set
the  y-limit  to (0,349) or (0,399), respectively.  Since  the  default
width  of 640 pixels is correct for most video modes,  xLimit() is only
necessary  when using SuperVGA graphics.  (See the section on  SuperVGA
support) Both xLimit() and yLimit() can also be used to limit the mouse
cursor to a small portion of the screen, such as a menu.

    You  may want to use a mouse cursor other than the default  cursor.
To do this,  call the function SetCursor() with the appropriate  cursor
name.  Many programs (especially graphics) will use  several  different
cursors  depending on the location of the mouse (such as an  arrow  for
menus  and  an i-beam for text) or the particular function  being  pro-
cessed (such as an hourglass for wait).  Several cursors are predefined
in the file cursor.h.  To use them,  simply include this header file in
whatever  module changes the cursor.  For more information on  cursors,
see the Mouse Cursors section.

    Finally,  you may want to set the motion parameters,  which include
the  mickey-to-pixel ratio and the double-speed threshold.  The mickey-
to-pixel  ratio  is set by MickToPix() and defines how many mickeys  it
takes  to move the mouse 8 pixels.  (A mickey is single count of  mouse
motion. Most mice are 200 "dots-per-inch", which means that one inch of
movement  results in 200 mickeys.)  If both the x and y parameters  are
set  to 8,  then there will be a one-to-one correlation  between  mouse
motion  and cursor motion.  The default values are 8 in the  horizontal
direction and 16 for the vertical.  The vertical value of 16 means  the
mouse must be moved twice as far vertically as horizontally to  get the
same cursor movement.  This is fine for text mode where the  equivalent
screen  resolution  of 640x200 results in an  equivalent  pixel  aspect
ratio of 2.4-to-1.  In EGA/VGA graphics mode the y-direction will  seem
noticeably  slower,  particularly for 640x480 which has  an  equivalent
pixel  aspect ratio of 1-to-1.  A vertical ratio of 8 will  cure  this.
The lower the ratio, the farther the cursor will move for a given mouse
movement.  Setting either ratio lower than 8 means that the cursor can-
not be located on every pixel. For example, setting the ratio to 4 will
cause  the cursor to move 2 pixels for every mickey.  The  double-speed
threshold  is set by a call to SetSpeedThreshold().  When the speed  of
the mouse (in mickeys per second) exceeds the speed parameter passed to
SetSpeedThreshold(), the motion speed of the cursor will double. A com-
plete initialization might look like this:

	#include "mouse.h"
	#include "cursor.h"

	main()
	{
	  { initialize screen };
	  if(mouse.Exists())
	  {
	    mouse.SetCursor(cross);
	    mouse.yLimit(0,479);	// VGA 640x480
	    mouse.MickToPix(8,8);
	    mouse.SetSpeedThreshold(32);
	    mouse.Enable();
	    mouse.Show();
	    ...
	  }
	}

    The  mouse should be reset before your program terminates  so  that
the  calling program does not inherit any strange parameters.  This  is
particularly true of the event handler. Because it is an interrupt rou-
tine,  failure to reset the mouse could lead to a system crash  if  the
handler is still pointing to the address of what used to be your  hand-
ler routine. The destructor Mouse::~Mouse() first resets the mouse sta-
tus by calling function 00h, and then restores the original event hand-
ler with function 14h.

-----------------------------------------------------------------------

Reading the Mouse

    Most  of the standard mouse functions stuff any return  values  di-
rectly  into the class variables and have a return type void.  This  is
because many mouse functions return more than one item of  information.
You  can then use the appropriate inline function to read the  required
private  variable.  To check for the mouse position, for instance,  you
would call Position() followed by either x() or y(), or both, such as:

	for(;;)
	{
	  mouse.Position();
	  if(mouse.x() > 320 || mouse.y() > 100)
	    do_something();
	}

This  method has the advantage of capturing both the x and y  positions
with  a single function call,  and those variables can then be read  at
your  leisure.  However,  we generally don't care where  the  mouse  is
located  unless  a button event that we are looking for  has  occurred.
Position() also returns the status of the mouse buttons, so we can also
check them:

	for(;;)
	{
	  mouse.Position();
	  if(mouse.LB_Dn())		// check for left button down
	  {
	    if(mouse.x() > 320 || mouse.y() > 100)
	      do_something();
	  }
	  else
	    do_something_else();
	}

This  loop will continuously check to see if the left button  has  been
pressed.  If the do_something_else() code is slow then there is a  pos-
sibility  that a button press could be missed since Position()  returns
the  real-time status of the mouse.  That is, during execution  of  the
do_something_else()  code,  the mouse button could be pressed  and  re-
leased and Position() would not capture it. The functions Pressed() and
Released() are best suited for checking for a button event because they
will return the button status since the last time they were called. For
example, this code

	for(;;)
	{
	  if(mouse.Pressed(LEFTBUTTON))
	  {
	    if(mouse.x() > 320 || mouse.y() > 100)
	    do_something();
	  }
	  else
	    do_something_else();
	}

is guaranteed to capture a button press even if the do_something_else()
code is slow to execute. Since Pressed() and Released() also return the
cursor position, a separate call to Position() is not necessary.

    In using the mouse,  it is often necessary to know if the cursor is
located  within a certain area of the screen.  For example,  in a  menu
interface,  you want to know if the cursor is located on a menu  selec-
tion  when a mouse button is clicked.  The function InBox()  adds  this
capability.  The parameters passed describe the upper  left  and  lower
right corners of the box. The return value is 1 if the cursor is in the
box, 0 if not. Therefore, the code

	if(mouse.InBox(40,40,100,100))

will  be true if the mouse cursor is in a box with corners (40,40)  and
(100,100). Like other mouse functions, the coordinates are pixels, even
if the screen is in text mode.

    In some cases you may want to hide the cursor if it falls inside  a
certain area.  The mouse driver provides such a function which,  in  my
opinion, has two drawbacks. Function 10h defines an exclusion window in
which  the mouse cursor will turn itself off.  However,  the programmer
must  then manually turn the cursor back on once it is outside the  ex-
clusion area,  and this requires continuously checking the mouse  posi-
tion, such as:

	for(;;)
	{
	  mouse.Exclude(40,40,100,100);
	  do_some_processing();
	  if(!mouse.InBox(40,40,100,100))
	    mouse.show();
	}

The  other problem with function 10h is that it only looks at  the  hot
spot  when checking the cursor's position, so part of the cursor  could
enter the exclusion area before the hot spot. The whole point of defin-
ing  an exclusion area is to turn the cursor off if it enters  the  de-
fined area. The Mouse++ Exclude() function is based on the InBox() fun-
ction, taking into account the hot spot location,  cursor image  height
and width, and cursor visibility.

    Finally,  if  your program is performing a time-consuming  task  in
which mouse input is not needed, you may want to disable the mouse.  If
the  mouse  is not disabled,  the user might become frustrated  with  a
mouse  that does not respond, and the event buffer could become  filled
with useless events. Calling the function Disable() will turn the mouse
off and disable the interrupt handler. The mouse and interrupt  handler
are re-enabled with the next call to Enable(),  although the mouse cur-
sor must be turned on with an explicit call to Show():

	...
	mouse.Disable();
	do_some_long_processing();
	mouse.Enable();
	mouse.Show();
	...

-----------------------------------------------------------------------

Mouse Cursors

    Mouse++ currently supports standard text and graphics cursors,  and
has rudimentary support for ColorGraphicsCursors. The mouse cursor type
and  shape are set by the function SetCursor().  In graphics mode,  the
cursor  is initially set to the familiar upper left pointing  arrow  by
the  mouse driver.  A standard graphics cursor is up to 16x16 pixels in
size  and moves in single pixel increments.  It is defined by a  screen
mask  (background),  an overlying cursor mask (foreground),  and a  hot
spot. Since the cursor is 16x16 pixels, a single-pixel hot spot must be
defined so that a unique pixel position can be determined for the  cur-
sor. The hot spot has x and y values with valid ranges of 0 to 15.

    The two masks determine how the screen will appear where the cursor
is located.  The screen mask is first ANDed with the screen pixels, and
the  cursor mask is then XORed with the resulting screen.  If a  screen
mask bit is 0 it will set the underlying screen pixel to 0 (black), and
if  the screen mask bit is 1 the pixel color will not change.  A cursor
mask bit of 0 does nothing, and a cursor mask bit of 1 will invert  the
underlying pixel color.  Since the masks have only values of 1 or 0 for
each  pixel  location,  but each pixel can have  a  color,  you  cannot
achieve  complete control of the cursor color using a standard  cursor.
The  two  basic choices are a black and white cursor where  the  screen
mask bits are 0,  or a cursor that inverts the screen colors where  the
screen mask bits are 1.

    Figure 1  shows the default cursor as an example.  The screen  mask
alone will set the screen pixels to black for the bits that are 0, cre-
ating a black arrow.  The cursor mask bits that are 1 will then  invert
the screen color, meaning part of the black arrow will become white. If
you lay the cursor mask directly over the screen mask,  you will notice
that  the  screen mask arrow extends one pixel beyond the  cursor  mask
arrow.  Because a screen mask bit 0 will create a black background  for
the cursor mask, this has the effect of putting a one pixel black  bor-
der around the cursor.  The reason for doing this is to make the cursor
visible  even where the screen background is white.  Making the  screen
mask  bits all 1's so that the cursor XOR's with the underlying  screen
is  useful in creating a CAD cursor (such as a "+" or a "x") that  must
be  one pixel wide.  The best way to get a better understanding of  the
graphics cursor is to try some out.  cursor.h defines several  graphics
cursors.

-----------------------------------------------------------------------

	0011111111111111	0000000000000000
	0001111111111111	0100000000000000
	0000111111111111	0110000000000000
	0000011111111111	0111000000000000
	0000001111111111	0111100000000000
	0000000111111111	0111110000000000
	0000000011111111	0111111000000000

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -