Keyboard & Mouse Input "The computer is down. I hope it's something serious." Stanton Delaplane The totINPUT unit includes two objects for managing the mouse and key- board. KeyOBJ is the main object for determining mouse and keyboard activity. MouseOBJ controls the location and shape of the mouse cursor. Mouse support is provided for Microsoft two-button, Logitech three- button, and 100% compatible mice. Getting Keyboard and Mouse Input totINPUT includes a global instance KEY of type KeyOBJ. In the same way that the instance SCREEN is used for all screen writes, the KEY instance should be used for all keyboard and mouse polling. Key includes methods for determining which key or mouse button was pressed, checking the status of the Alt/Ctrl/Shift keys, controlling the Num/Scroll/Caps lock keys, setting the keyboard repeat rate, and stuffing the keyboard buffer. There are also two special user hooks which provide easy ways to cus- tomize your program. The idle hook allows you to perform some action (like displaying a ticking clock) while the program is idle waiting for user input. The character hook allows you to intercept every user action, and is called every time a key is pressed or a mouse button is clicked. Setting Mouse Methods Users of TechnoJock's Turbo Toolkit (TTT) may recall that the input routines supported an "invisible" mouse cursor. If the user moved the mouse while a program was waiting for a key press, a special code was returned which indicated that the mouse had been moved either up, down, left or right. Most of the TTT units would respond to the mouse move- ment as though a cursor key had been pressed. TechnoJock's Object Toolkit provides much more extensive mouse support. However, if you want to make your programs respond like the original TTT, you can with the following SetMouseMethod method: SetMouseMethod(Method:byte); 6-2 User's Guide -------------------------------------------------------------------------------- This method instructs the Toolkit on which form of mouse support to provide. If a 0 is passed, or if there is no mouse detected, the object will ignore any mouse activity. If a 1 is passed, an "invisible" mouse will be supported, and if a 2 is passed, full mouse support is enabled. If you want to temporarily disable mouse support, set the mouse method to 0, which can later be set back to 1 or 2. When the mouse method is set to 1, the following two methods control how much the mouse must be moved before the movement is detected: SetHoriz(Sensitivity:byte); This method is passed the number of characters that the mouse cursor must be moved horizontally before a MouseLeft or MouseRight code is returned. SetVert(Sensitivity:byte); This method is passed the number of characters that the mouse cursor must be moved vertically before a MouseUp or MouseDown code is returned. Determining User Input The heart of the KeyOBJ object is the GetInput method. GetInput pauses program execution and waits for the user to press a key, or click a mouse button (or move the mouse, if the MouseMethod is set to 1). The user action can be determined by calling the functions Lastkey, LastX and LastY. These functions return the key/button(s) which were pressed, and the (X,Y) location of the mouse when the action took place, respec- tively. Another method, GetKey, automatically calls GetInput, and returns the user action code -- this saves calling GetInput followed by LastKey. The method DelayKey is like GetInput, but will only pause for user input for a specified number of milliseconds. This method is useful for displaying temporary messages and the like. If a key has not been pressed after a specified time period, Lastkey is updated with a value of 0. Unlike Turbo Pascal, the Toolkit uses a WORD sized variable to record the user activity. As well as supporting the standard keyboard, KeyOBJ reports mouse button activity, as well as many special key combina- tions, e.g. Alt-TAB. Refer to table 6.1 for a full list of the KeyOBJ action codes. Some of the action codes listed in the table are raised Keyboard & Mouse 6-3 -------------------------------------------------------------------------------- by totWIN objects which indicate that the mouse was clicked on a spe- cial window icon. Refer to chapter 7: Using Windows for further infor- mation. 6-4 User's Guide -------------------------------------------------------------------------------- Table 6.1 Key Action Codes Key Norm Shift Alt Ctrl Key Norm Shift Alt Ctrl a 97 65 286 1 F1 315 340 360 350 b 98 66 304 2 F2 316 341 361 351 c 99 67 302 3 F3 317 342 362 352 d 100 68 288 4 F4 318 343 363 353 e 101 69 274 5 F5 319 344 364 354 f 102 70 289 6 F6 320 345 365 355 g 103 71 290 7 F7 321 346 366 356 h 104 72 291 8 F8 322 347 367 357 i 105 73 279 9 F9 323 348 368 358 j 106 74 292 10 F10 324 349 369 359 k 107 75 293 11 F11 389 391 395 393 l 108 76 294 12 F12 390 392 396 394 m 109 77 306 13 n 110 78 305 14 BkSp 8 8 270 127 o 111 79 280 15 Up 328 428 408 397 p 112 80 281 16 Down 336 436 416 401 q 113 81 272 17 Left 331 431 411 371 r 114 82 275 18 Right 333 433 413 372 s 115 83 287 19 End 335 435 415 373 t 116 84 276 20 Home 327 427 407 375 u 117 85 278 21 PgUp 329 429 409 388 v 118 86 303 22 PgDn 337 437 417 374 w 119 87 273 23 Ins 338 261 418 260 x 120 88 301 24 Del 339 263 419 262 y 121 89 277 25 Tab 9 271 421 404 z 122 90 300 26 Esc 27 27 257 27 Enter 13 13 284 10 1 ! 49 33 376 - 2 @ 50 64 377 259 , < 44 60 307 - 3 # 51 35 378 - . > 46 62 308 - 4 $ 52 36 379 - / ? 47 63 309 - 5 % 53 37 380 - ; : 59 58 295 - 6 ^ 54 94 381 30 ' " 39 34 296 - 7 & 55 38 382 - [ { 91 123 282 27 8 * 56 42 383 - ] } 93 125 283 29 9 ( 57 40 384 - \ | 92 124 299 28 0 ) 48 41 385 - - _ 45 95 386 31 = + 61 43 387 - Keyboard & Mouse 6-5 -------------------------------------------------------------------------------- Table 6.1 Key Action Codes (Contd.) Mouse Action Code Window Action Code Left Click 513 Close Icon Selected 600 Right Click 514 Window Moved 601 Middle Click 515 Window Resized 602 Left + Right 516 Scroll Bar Up 610 Left + Middle 517 Scroll Bar Down 611 Middle + Right 518 Scroll Bar Left 612 All three 519 Scroll Bar Right 613 Left Double 523 Vertical Elevator 614 Right Double 524 Horizontal Elevator 615 Middle Double 525 Mouse Up 584 Mouse Down 592 Mouse Left 589 Mouse Right 587 Note: the upper ASCII characters are also returned if the user holds down the Alt key and presses the 3-digit ASCII code on the numeric keypad, or if an international code page is active. In other words, the input routines fully support international characters, line drawing, and all other extended ASCII characters. In most cases, you will use the global instance Key to determine user input. However, if you want to use an independent instance, make sure you initialize the instance by calling the INIT method. The function method Extended will return true if an extended keyboard is installed. Listed below is the syntax for the user input methods: GetInput; Pauses program execution until a key or mouse button is pressed. GetKey: word; Pauses program execution until a key or mouse button is pressed, and returns a word value indicating the user action, (see Table 6.1) LastKey: word; 6-6 User's Guide -------------------------------------------------------------------------------- Returns a word value indicating the last user action, (see Table 6.1) LastChar: char; If the action code of the LastKey was less than 256, the character equivalent of the code is returned, otherwise a #0 is returned. LastX: byte; Returns the X Coordinate of the mouse cursor when the last key action was recorded. LastY: byte; Returns the Y Coordinate of the mouse cursor when the last key action was recorded. DelayKey(Mills:longint); This function is similar to GetInput, except that the method will only wait for Mills milliseconds. If the user is not active in the specified period, a #0 is recorded as the last key. Extended:boolean; This function method returns true if the system has an extended key- board installed. The following example shows how you might pause for some user action, and then check the pressed key to decide which routines to execute next: ... Key.GetInput case Key.LastKey of 27: EscapeRoutine; 13: EnterRoutine; 513: LeftButtonRoutine(Key.LastX,Key.LastY); ... end; {case} ... The following example, DEMIN1.PAS, repeatedly waits for some user action, and displays the value of each action code: Program DemoInputOne; {DEMIN1} Keyboard & Mouse 6-7 -------------------------------------------------------------------------------- Uses CRT, totINPUT; begin Clrscr; Writeln('Press any key or mouse button combination. (Esc to quit)'); Key.SetDouble(true); repeat Key.GetInput; GotoXY(1,2); Write('You pressed key: ',Key.LastKey,' '); until Key.LastKey = 27; end. Note: The Toolkit reports double-clicking on any of the mouse but- tons. You may have used some software products which make the user double-click the mouse at "lightning" speed. This problem occurs because the software wants to respond as soon as possible to any mouse activity. So, when a button is clicked, the software doesn't wait around for very long to see if the same button has been clicked again. If you are not quick enough, a double-click is reported as one or two single clicks of the same button. The Toolkit has the same design dilemma: fast response, with enough time so a non-athlete can double-click a button! The Tool- kit solution is to allow you to set whether the system should wait for a double-click. KeyOBJ includes the method SetDouble, which is passed a boolean parameter. Pass a TRUE parameter to allow a little extra time for double-clicks. If you don't care about double-clicks, call SetDouble(false);. You can freely switch between the two states throughout the program. By default, Key does not pause for double-clicks. The function method GetDouble returns the current double-click setting. You can experiment with the impact of the SetDouble method by trying the above example with SetDouble enabled and disabled. 6-8 User's Guide -------------------------------------------------------------------------------- Accessing Ctrl, Alt and Shift KeyOBJ supports a wide variety of special key combinations like Alt- Backspace and Ctrl-PgUp. Sometimes, however, you may want to know if one of the shifting keys is being pressed on its own. GetInput will not respond when Alt, Ctrl or either Shift key is pressed. It waits for a standard alphanumeric key to be pressed. KeyOBJ does, however, provide the following five methods to let you check the status of these special shifting keys: AltPressed:boolean; Returns true if the Alt key is being held down. CtrlPressed: boolean; Returns true if the Ctrl key is being held down. LeftShiftPressed: boolean; Returns true if the left Shift key is being held down. RightShiftPressed: boolean; Returns true if the right Shift key is being held down. ShiftPressed: boolean; Returns true if either Shift key is being held down. These methods are useful if you want to display an indicator which illuminates when the special keys are pressed. The demo program, DEMIN2.PAS, discussed in the next section, illustrates this technique. Accessing Num, Scroll and Caps Lock The KeyOBJ provides the following six methods for determining and changing the status of the Num Lock, Scroll Lock and Caps Lock keys: SetCaps(On:boolean); Pass TRUE to turn on the Caps Lock key, or FALSE to turn it off. SetNum(On:boolean); Pass TRUE to turn on the Num Lock key, or FALSE to turn it off. Keyboard & Mouse 6-9 -------------------------------------------------------------------------------- SetScroll(On:boolean); Pass TRUE to turn on the Scroll Lock key, or FALSE to turn it off. GetCaps:boolean; Returns TRUE if the Caps Lock is on, and FALSE if it is off. GetNum:boolean; Returns TRUE if the Num Lock is on, and FALSE if it is off. GetScroll:boolean; Returns TRUE if the Scroll Lock is on, and FALSE if it is off. The following demo program, DEMIN2.PAS, shows how to use the shifting and locking keys. Program DemoInputTwo; {DEMIN2} Uses CRT, totINPUT, totFAST; begin with Screen do begin Clear(31,' '); PartClear(1,23,80,25,94,' '); WritePlain(10,5,'Press Num, Scroll, Caps Lock, or hold down the Alt,'); WritePlain(10,6,'Ctrl, Left/Right Shift keys. The active keys will be'); WritePlain(10,7,'highlighted at the foot of the display.'); WritePlain(10,9,'Any other key quits.'); with Key do begin SetCaps(true); SetNum(true); SetScroll(true); repeat if GetCaps then WritePlain(40,24,'CAPS') else WritePlain(40,24,' '); if GetNum then WritePlain(45,24,'NUM') 6-10 User's Guide -------------------------------------------------------------------------------- else WritePlain(45,24,' '); if GetScroll then WritePlain(50,24,'SCROLL') else WritePlain(50,24,' '); if AltPressed then WritePlain(60,24,'Alt') else WritePlain(60,24,' '); if CtrlPressed then WritePlain(65,24,'Ctrl') else WritePlain(65,24,' '); if LeftShiftPressed then WritePlain(70,24,'L-^X') else WritePlain(70,24,' '); if RightShiftPressed then WritePlain(75,24,'R-^X') else WritePlain(75,24,' '); until KeyPressed; SetCaps(false); SetNum(false); SetScroll(false); end; end; end. Note: The methods for setting and getting the status of the lock- ing keys will only function on 100% IBM BIOS compatible systems. Setting the Keyboard Repeat Rate, and Clicking The PC keyboards support a typematic effect i.e. holding a key pressed down has the same effect as pressing the key multiple times. By default, a key must be held down for about half a second before the repetition commences, and then about ten characters per second are sent. Most users think this repeat rate is too slow (especially for cursor movement) and the Toolkit provides a way of changing it. Keyboard & Mouse 6-11 -------------------------------------------------------------------------------- Commencing with the IBM-AT, the ROM BIOS keyboard services provided a way to change the typematic rate. The earliest ROM BIOS to feature configurable typematic delays was 11/15/85. The following three KeyOBJ methods can be used to modify the typematic rate on systems with the required BIOS: SetFast; Set the typematic rate to a fast 30 characters per second, i.e. there is very little delay between repeats. SetSlow; Sets the typematic rate to 5 characters per second. SetRepeatRate(QSDelay,Rate:byte); This method allows you to explicitly set the typematic rate. The first parameter accepts a value between 1 and 4, and indicates the number of quarter seconds delay before the key commences repeating, e.g. 3 repre- sents a 750 millisecond delay. The second parameter indicates the repeat rate, and accepts a value between 0 and 31. The following table shows the repeat rate parameter followed by the corresponding character per second repeat rate: 0 30.0 7 16.0 14 8.6 21 4.6 28 2.5 1 26.7 8 15.0 15 8.0 22 4.3 29 2.3 2 24.0 9 13.3 16 7.5 23 4.0 30 2.1 3 21.8 10 12.0 17 6.7 24 3.7 31 2.0 4 20.0 11 10.9 18 6.0 25 3.3 5 18.5 12 10.0 19 5.5 26 3.0 6 17.1 13 9.2 20 5.0 27 2.7 Note: keyboard ROM BIOS provides no way of determining the current typematic rate setting. The typematic rate is set in BIOS, and so the methods will affect the typematic rate for the rest of the session, even after the program has terminated. Do you remember how typewriters used to click? Well, the Toolkit pro- vides a way of emitting an electronic click every time a key is pressed. The following method can be used to control keyboard clicking: SetClick(On:boolean); Pass TRUE to activate clicking, or FALSE to switch it off. By default, clicking is off. 6-12 User's Guide -------------------------------------------------------------------------------- The demo program DEMBR1.PAS is designed to illustrate the BrowseOBJ object which is discussed in chapter 9. There are, however, some Key statements included. Execute the demo program and experiment with the typematic rate. Using the Keyboard Buffer The KeyOBJ uses an internal buffer for storing keystrokes. The sole purpose of this buffer is to allow you to force characters into the buffer using the methods StuffBuffer and StuffBufferStr. GetInput (and therefore GetKey/GetChar) also checks the characters in the buffer before checking the keyboard. By default, the size of the buffer is 30 characters, but this can be easily modified by changing the StuffBufferSize constant at the top of the totINPUT unit. Listed below is the syntax of the buffer related methods: StuffBuffer(W:word); This forces a key into the keyboard buffer. The parameter passed is the word value of the character, as detailed in Table 6.1. StuffBufferStr(Str:string); This stuffs characters (with ASCII values in the range 0 to 255) into the keyboard buffer. This method is provided as a convenience to save making multiple calls to StuffBuffer (one call for every character in the string). FlushBuffer; Erases all the keys in the keyboard buffer. KeyPressed: boolean; Use this method in preference to Turbo Pascal's Keypressed function, because it checks the internal buffer as well as the keyboard buffer. The keyboard stuffing capabilities form the framework for a simple but elegant macro facility. A full example, DEMIN3.PAS, illustrates this concept and is discussed in the next section. Keyboard & Mouse 6-13 -------------------------------------------------------------------------------- Assigning Keyboard Hooks The KeyOBJ object allows you to assign a procedure which will be called while the program is idle and waiting for the user to press a key. Similarly, the object allows you to assign a procedure which will be called every time a character is pressed. These two types of procedures are referred to as an Idle Hook and a Pressed Hook, respectively. IMPORTANT NOTE: If you write to the display from a hooked procedure, you need to be aware that the active routine may have the display window set. To avoid any problems, use the Screen method SetWinIgnore to temporarily disable the window setting. Refer to page 5-17 for fur- ther details. Idle Hook An idle hook is an external procedure which will be repeatedly called while the program is waiting for the user to input data. A good use for an idle hook is to display a ticking clock that is always updated, or to show the status of the "shift" and "lock" keys. All you have to do is create a procedure following some specific rules, and then call the method Key.AssignIdleHook to instruct the Key object to call your procedure. For a procedure to be eligible as an idle hook it must adhere to the following three rules: Rule 1 The procedure must be declared as a FAR procedure. This can be achieved by preceding the procedure with a {$F+} compiler directive, and following the procedure with a {$F-} direc- tive. Alternatively, Turbo 6 users can use the new keyword FAR following the procedure statement. Rule 2 The procedure must be declared with no (nada/zero/none) passed parameters. Rule 3 The procedure must be at the root level, i.e. the procedure cannot be nested within another procedure. The following procedure declaration follows these rules: {$F+} procedure MyIdleHook; .....{procedure statements} end; {$F-} The following method AssignIdleHook is then called to instruct the Toolkit to call your procedure while the system is waiting for input: 6-14 User's Guide -------------------------------------------------------------------------------- AssignIdleHook(PassedProc:InputIdleProc); This method is passed the procedure name of a procedure declared using the rules outlined above. Your procedure will be continually called while your program is waiting for user input, so make sure that the procedure is compact and effi- cient. If your procedure involves too many tasks, the program will slow down considerably during input. If you want to call an extended task like a background print program, you must continually check the Key.Keypressed function method and suspend your procedure when it returns true. If subsequently, you want to remove your idle hook, execute the follow- ing: Key.AssignIdleHook(NoInputIdleHook); Pressed Hook A pressed hook is a procedure which is called every time a key is pressed or a mouse button is clicked. This is particularly useful for trapping special keys like [KEYCAP] for help, or for building keyboard macros. All you have to do is create a procedure following some specific rules, and then call the method Key.AssignPressedHook to instruct the Key object to call your procedure each time a key is pressed. For a procedure to be eligible as a pressed hook it must adhere to the following three rules: Rule 1 The procedure must be declared as a FAR procedure. This can be achieved by preceding the procedure with a {$F+} compiler directive, and following the procedure with a {$F-} direc- tive. Alternatively, Turbo 6 users can use the new keyword FAR following the procedure statement. Rule 2 The procedure must be declared with one passed parameter, and this parameter must be a variable parameter of type word, e.g. (var W:word);. Rule 3 The procedure must be at the root level, i.e. the procedure cannot be nested within another procedure. The following procedure declaration follows these rules: Keyboard & Mouse 6-15 -------------------------------------------------------------------------------- {$F+} procedure MyPressedHook(var K:word); .....{procedure statements} end; {$F-} The following method AssignPressedHook is then called to instruct the Toolkit to call your procedure when the system receives input: AssignPressedHook(PassedProc:InputPressedProc); This method is passed the procedure name of a procedure declared using the rules outlined above. The parameter passed to your procedure is the value of the key (or mouse button) just pressed, as detailed in Table 6.1. Test the value of the parameter, and decide what action to take. As with the idle hook, keep the hooked procedure small and efficient to avoid program execu- tion delays. When your procedure terminates, the character is then processed in the normal manner by your program. If you want the character to be ignored, set the passed parameter value to 0. You can also use this facility to swap the meaning of keys. For example, the following code fragment intercepts the double-quote and replaces it with a single-quote. {$F+} procedure DoubleGrabber(var Keycode: word); begin if KeyCode = 34 then KeyCode := 39; end; {$F-} begin ..... AssignedPressedHook(DoubleGrabber); ..... end. If you subsequently want to disable the pressed hook, use the following statement: Key.AssignPressedHook(NoInputPressedHook); 6-16 User's Guide -------------------------------------------------------------------------------- Hook Example The following demo program, DEMIN3.PAS, illustrates how to use the idle and pressed hooks, and many other KeyOBJ features: Program DemoInputThree; {DEMIN3} Uses CRT, totINPUT, totFAST, totMISC; {$F+} procedure ClockHook; {} begin with Screen do with Key do begin SetWinIgnore(true); if GetCaps then WritePlain(40,24,'CAPS') else WritePlain(40,24,' '); if GetNum then WritePlain(45,24,'NUM') else WritePlain(45,24,' '); if GetScroll then WritePlain(50,24,'SCROLL') else WritePlain(50,24,' '); if KeyPressed then begin SetWinIgnore(false); exit; end; if AltPressed then WritePlain(60,24,'Alt') else WritePlain(60,24,' '); if CtrlPressed then WritePlain(65,24,'Ctrl') else WritePlain(65,24,' '); if LeftShiftPressed then WritePlain(70,24,'L-^X') else WritePlain(70,24,' '); if RightShiftPressed then WritePlain(75,24,'R-^X') Keyboard & Mouse 6-17 -------------------------------------------------------------------------------- else WritePlain(75,24,' '); if KeyPressed then begin SetWinIgnore(false); exit; end; WritePlain(1,24,CurrentTime); SetWinIgnore(false); end; end; {ClockHook} {$F-} {$F+} procedure MacroHook(var W:word); {} begin case W of 286: begin Key.StuffBufferStr(' Apple '); {Alt-A} W := 0; end; 304: begin Key.StuffbufferStr(' Bravo '); {Alt-B} W := 0; end; 301: begin Key.StuffBuffer(27); {Alt-X} W := 0; end; 315: begin Key.StuffbufferStr(' No help! '); {F1} W := 0; end; end; {case} end; {MacroHook} {$F-} begin with Screen do begin Clear(31,' '); PartClear(1,23,80,25,94,' '); WritePlain(5,1,'Press any alpha characters, or Alt-A,B for macros. Esc or Alt-X to quit'); GotoXY(1,3); with Key do begin 6-18 User's Guide -------------------------------------------------------------------------------- SetCaps(true); SetNum(true); SetScroll(true); AssignIdleHook(ClockHook); AssignPressedHook(MacroHook); Repeat GetInput; Write(LastChar); Until LastKey = 27; SetCaps(false); SetNum(false); SetScroll(false); end; end; end. Using the Mouse The Toolkit provides full mouse support, and any mouse activity is reported by the KeyOBJ object. Normally, you will not need to access the mouse directly, but in case you need to, the totINPUT unit includes the global instance MOUSE of type MouseOBJ. This instance can be used to control the mouse cursor and check the status of the mouse buttons. All the Toolkit mouse support is for text mode only - the Toolkit does not support the mouse in graphics mode. The following methods can be used to control the mouse cursor and check the mouse status: Installed: boolean; Returns true if a mouse and mouse driver are installed. Visible: boolean; Returns true if the mouse cursor is visible on the display. Hide; Hides the mouse cursor. Show; Displays the mouse cursor. Move(X,Y:integer); Keyboard & Mouse 6-19 -------------------------------------------------------------------------------- Moves the mouse cursor to the coordinates (X,Y). Note this command ignores the current window setting. Confine(X1,Y1,X2,Y2:byte); Restricts the mouse so that it can only move within the coordinates (X1,Y1) to (X2,Y2). Location(var X,Y:byte); Updates the variables X and Y with the current location coordinates of the mouse. Status(var L,C,R:boolean; var X,Y); Updates the L,C,R boolean variables to true if any of the Left, Center, or Right mouse buttons are depressed, and updates the variables X and Y with the current mouse location. Pressed(Button:integer; var X,Y:byte): byte; Returns the number of times the specified button has been pressed since the function was last called. Button values of 0,1 and 2 represent the Left, Right and Center buttons respectively. The variables X and Y are updated with the coordinates of the mouse the last time the button was pressed. Released(Button:integer; var X,Y:byte):byte; Returns the number of times the specified button has been released since the function was last called. Button values of 0,1 and 2 repre- sent the Left, Right and Center buttons respectively. The variables X and Y are updated with the coordinates of the mouse the last time the button was released. GetButtons: byte; Returns the number of buttons installed on the mouse. SetMouseCursorStyle(OrdChar,Attr:byte); Sets the mouse cursor to the character represented by the ASCII value OrdChar. The second parameter controls the display attribute of the mouse cursor. If a zero is specified, the Toolkit uses the standard mouse device driver technique, which changes color based on the under- lying screen attribute to ensure maximum contrast. If a non-zero attribute value is specified, the mouse cursor will be displayed in the specified attribute regardless of the screen display attributes. 6-20 User's Guide -------------------------------------------------------------------------------- SetLeft(On:boolean); The de facto standard in the industry is for the left button to be the "do it" or "enter" button, and this is the Toolkit default. Use the method SetLeft to control whether the left button or the right button is used as the action button. Pass a TRUE parameter to use the left, or a FALSE parameter to use the right. Reset; This method calls the mouse reset interrupt. The mouse is set back to the center of the display, the cursor style is set back to the default, and the mouse cursor is hidden. Listed below is the mouse demo program DEMIN4.PAS, followed by figure 6.1 which illustrates the output from the program. Program DemoInputFour; {DEMIN4} Uses CRT, totINPUT, totFAST, totSTR; Var Ch : char; L,C,R,OldL,OldC,OldR: boolean; X,Y,OldX,OldY: byte; begin Clrscr; with Mouse do begin if not Installed then begin Writeln('This demo will only function on systems equipped with a mouse'); end else begin WriteLn('You have a ',GetButtons,' button mouse!'); Writeln('Press: C to confine the mouse'); Writeln(' U to unconfine the mouse'); Writeln(' L to change the mouse cursor'); Writeln(' R to reset mouse'); Writeln(' H to hide the mouse'); Writeln(' S to show the mouse'); Writeln(' any mouse button'); Writeln(' Esc to quit'); Screen.FillBox(15,10,65,20,30,1); Show; Keyboard & Mouse 6-21 -------------------------------------------------------------------------------- repeat with Screen do repeat Status(L,C,R,X,Y); if OldL <> L then if L then WriteAT(20,11,30,'Left Button') else WriteAT(20,11,30,' '); if OldR <> R then if R then WriteAT(20,12,30,'Right Button') else WriteAT(20,12,30,' '); if OldC <> C then if C then WriteAT(20,13,30,'Middle Button') else WriteAT(20,13,30,' '); if OldX <> X then WriteAT(20,15,30,inttostr(X)+' '); if OldY <> Y then WriteAT(20,16,30,inttostr(Y)+' '); OldL := L; OldR := R; OldC := C; OldX := X; OldY := Y; until Key.KeyPressed; Key.GetInput; case upcase(Key.LastChar) of 'C': Confine(15,10,65,20); 'U': Confine(1,1,80,25); 'L': SetMouseCursorStyle(random(200)+56,0); 'H': Hide; 'S': Show; 'R': begin Hide; Reset; Show; end; end; {case} until Key.LastKey = 27; Hide; end; GotoXY(1,23); end; end. 6-22 User's Guide -------------------------------------------------------------------------------- Figure 6.1 [SCREEN] Using the MOUSE Object