User Interfaces


Of Mice And Menus

Keith Bugg


Keith Bugg is currently a senior software engineer with Analysas Corp. His ten years experience as a programmer/analyst includes five years in C, all on the DEC VAX or the PC. Readers may contact him at 122 E. Morningside Drive, Oak Ridge, TN 37830, (615) 482-9515.

Including a mouse in your application enhances its ease of use and friendliness. Novice users can find the large keyboard intimidating. Using a mouse to navigate a program can reduce this apprehension. Also, using a mouse lowers the learning curve — the simplicity of "point and click" reinforces the user's intuition.

The programmer benefits from the improved data integrity a mouse supplies. In a classic menu-driven system, the program must read the user's keystroke(s), validate results, and report on them. In a mouse-driven system, the user can only select a valid option. If the user clicks the mouse on a vacant area of the screen, the program simply ignores the clicks.

I describe here the design and implementation of a C program that allows a mouse to select options in a menu-driven application. The sample program demonstrates many of the technical issues, and can serve as a template in your collection of tools. I developed the code for an IBM PC running MS-DOS. The program requires a Microsoft mouse (or compatible), its associated driver, and the Microsoft mouse library, MOUSE.LIB. I used the Microsoft C compiler, but the code should work with other compilers with a minimum of changes. Whatever compiler you choose, you must buy MOUSE.LIB. It is available from Microsoft as part of the Microsoft Mouse Programmer's Guide, and costs about $25.

A program using the Microsoft mouse can be compiled in any of the memory models, and then linked with MOUSE.LIB, as in this example:

cl/AM  /c myprogram.c
   (creates a medium model but does not link)
link myprogram.obj,MOUSE.LIB
   (creates executeable of 'myprogram')
The Microsoft compiler switch /AM determines the memory model, in this case medium. Use /AS for small, /AC for compact, and /AL for large and huge.

The mouse library contains all the routines needed to manipulate the mouse. Utilities include reading the cursor, writing the cursor, and determining the status of mouse buttons. The Microsoft mouse performs 23 functions.

The call to mouse uses four parameters which are declared as integers and passed by reference, as in mouse (&m1, &m2, &m3, &m4). (Each argument of type pointer to int.) The first parameter indicates the command to be performed. The others provide additional information, such as cursor coordinates or button selection. Table 1 summarizes the calls most widely used.

Mouse coordinates differ from screen coordinates by a factor of eight when in text mode, because each character is an 8-by-8 pixel group. The upper left-hand corner of the screen is the origin. It has coordinates (0, 0). The lower right-hand corner of the screen has coordinates (632, 192), assuming the usual 25 lines of 80 characters each.

BIOS calls solve most of the technical design issues that affect including a mouse in a program. A mouse-driven program should begin by checking the target platform for the existence of a mouse and its driver. Your program can then adapt automatically to machines without a mouse. Incidentally, you might want menu options to be selected via the keyboard whether your target platform has a mouse or not. The sample program does not include this mode of operation, but you can easily include it. Programming for the arrow keys, the function keys, and other special keys (such as Home and End) is fairly straightforward.

The next issue concerns manipulating the cursors. You must control both the default text cursor and the mouse cursor. Use BIOS calls to control the text cursor. You can also use BIOS calls to access the video display. The sample program displays the example menu using BIOS calls. Use an array of structures to define the menu. Each element holds the text of the menu option plus the screen and mouse coordinates. With this approach, you can make changes easily.

When using a mouse in your applications, you should disable the control-break interrupt, and restore it upon termination. If you don't, and the user types a control-break, the program could return control to DOS with the text cursor off and the mouse cursor still on. This situation could confuse and frustrate the user. Remember that an important reason to using a mouse is to create a level of comfort and to reduce complexity. You access the control break interrupt by calling signal. See the Microsoft C documentation for a description of this function.

Although it is beyond the scope of this article, bear in mind that a well-designed application would save and restore the target platform's configuration. This includes the graphics mode and screen color, for example. The focus of this article is more on the fundamental requirements. At that level, little difference exists between a mouse-driven program and a traditional program. Both give the user information, wait for a response, and take action.

The sample program executes an infinite loop waiting for an event to occur. It ignores meaningless events such as clicking the mouse button on a vacant area of the menu. It processes valid ones such as backlighting a menu option when the mouse cursor is moved into it. Knowing the mouse's characteristics is essential for organizing the logic flow of an application.

Interfacing a mouse to an application brings a versatile and elegant dimension to the user-interface. All well-engineered software emphasizes what to do over how to do it. Mouse-driven programs are no exception. You can use the sample program as a template for other programs. Here are some suggestions: a pop-up calculator, a control panel in a process-control environment, a cut-and-paste buffer for a text editor, or a help screen with hypertext capabilities.

References

Microsoft Mouse Programmer's Reference Guide by Microsoft Press.

C Power Users Guide by Herb Schildt

Listing 1