home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / PASCAL / TOTDOC.ZIP / CHAPT6.TXT < prev    next >
Encoding:
Text File  |  1991-02-10  |  43.1 KB  |  1,062 lines

  1.                                                                         Keyboard
  2.                                                                                &
  3.                                                                            Mouse
  4.                                                                            Input
  5.  
  6.  
  7.  
  8.  
  9.  
  10.          "The computer is down. I hope it's something serious."
  11.  
  12.                                                                Stanton Delaplane
  13.  
  14.  
  15.  
  16.          The totINPUT unit includes two objects for managing the mouse and key-
  17.          board. KeyOBJ is the main object for determining mouse and keyboard
  18.          activity. MouseOBJ controls the location and shape of the mouse cursor.
  19.          Mouse support is provided for Microsoft two-button, Logitech three-
  20.          button, and 100% compatible mice.
  21.  
  22.  
  23.  
  24. Getting Keyboard and Mouse Input
  25.  
  26.          totINPUT includes a global instance KEY of type KeyOBJ. In the same way
  27.          that the instance SCREEN is used for all screen writes, the KEY
  28.          instance should be used for all keyboard and mouse polling. Key
  29.          includes methods for determining which key or mouse button was pressed,
  30.          checking the status of the Alt/Ctrl/Shift keys, controlling the
  31.          Num/Scroll/Caps lock keys, setting the keyboard repeat rate, and
  32.          stuffing the keyboard buffer.
  33.  
  34.          There are also two special user hooks which provide easy ways to cus-
  35.          tomize your program. The idle hook allows you to perform some action
  36.          (like displaying a ticking clock) while the program is idle waiting for
  37.          user input. The character hook allows you to intercept every user
  38.          action, and is called every time a key is pressed or a mouse button is
  39.          clicked.
  40.  
  41.  
  42.  
  43. Setting Mouse Methods
  44.  
  45.          Users of TechnoJock's Turbo Toolkit (TTT) may recall that the input
  46.          routines supported an "invisible" mouse cursor. If the user moved the
  47.          mouse while a program was waiting for a key press, a special code was
  48.          returned which indicated that the mouse had been moved either up, down,
  49.          left or right. Most of the TTT units would respond to the mouse move-
  50.          ment as though a cursor key had been pressed.
  51.  
  52.          TechnoJock's Object Toolkit provides much more extensive mouse support.
  53.          However, if you want to make your programs respond like the original
  54.          TTT, you can with the following SetMouseMethod method:
  55.  
  56.  
  57.          SetMouseMethod(Method:byte);
  58.  
  59.  
  60. 6-2                                                                 User's Guide
  61.  
  62. --------------------------------------------------------------------------------
  63.  
  64.          This method instructs the Toolkit on which form of mouse support to
  65.          provide. If a 0 is passed, or if there is no mouse detected, the object
  66.          will ignore any mouse activity. If a 1 is passed, an "invisible" mouse
  67.          will be supported, and if a 2 is passed, full mouse support is enabled.
  68.          If you want to temporarily disable mouse support, set the mouse method
  69.          to 0, which can later be set back to 1 or 2.
  70.  
  71.  
  72.  
  73.          When the mouse method is set to 1, the following two methods control
  74.          how much the mouse must be moved before the movement is detected:
  75.  
  76.  
  77.          SetHoriz(Sensitivity:byte);
  78.  
  79.          This method is passed the number of characters that the mouse cursor
  80.          must be moved horizontally before a MouseLeft or MouseRight code is
  81.          returned.
  82.  
  83.  
  84.          SetVert(Sensitivity:byte);
  85.  
  86.          This method is passed the number of characters that the mouse cursor
  87.          must be moved vertically before a MouseUp or MouseDown code is
  88.          returned.
  89.  
  90.  
  91.  
  92. Determining User Input
  93.  
  94.          The heart of the KeyOBJ object is the GetInput method. GetInput pauses
  95.          program execution and waits for the user to press a key, or click a
  96.          mouse button (or move the mouse, if the MouseMethod is set to 1). The
  97.          user action can be determined by calling the functions Lastkey, LastX
  98.          and LastY. These functions return the key/button(s) which were pressed,
  99.          and the (X,Y) location of the mouse when the action took place, respec-
  100.          tively.
  101.  
  102.          Another method, GetKey, automatically calls GetInput, and returns the
  103.          user action code -- this saves calling GetInput followed by LastKey.
  104.  
  105.          The method DelayKey is like GetInput, but will only pause for user
  106.          input for a specified number of milliseconds. This method is useful for
  107.          displaying temporary messages and the like. If a key has not been
  108.          pressed after a specified time period, Lastkey is updated with a value
  109.          of 0.
  110.  
  111.          Unlike Turbo Pascal, the Toolkit uses a WORD sized variable to record
  112.          the user activity. As well as supporting the standard keyboard, KeyOBJ
  113.          reports mouse button activity, as well as many special key combina-
  114.          tions, e.g. Alt-TAB. Refer to table 6.1 for a full list of the KeyOBJ
  115.          action codes. Some of the action codes listed in the table are raised
  116.  
  117.  
  118.  
  119. Keyboard & Mouse                                                             6-3
  120.  
  121. --------------------------------------------------------------------------------
  122.  
  123.          by totWIN objects which indicate that the mouse was clicked on a spe-
  124.          cial window icon. Refer to chapter 7: Using Windows for further infor-
  125.          mation.
  126.  
  127.  
  128.  
  129. 6-4                                                                 User's Guide
  130.  
  131. --------------------------------------------------------------------------------
  132.  
  133. Table 6.1
  134. Key Action Codes
  135.  
  136.            Key  Norm   Shift  Alt    Ctrl     Key   Norm   Shift  Alt    Ctrl
  137.            a    97     65     286    1        F1    315    340    360    350
  138.            b    98     66     304    2        F2    316    341    361    351
  139.            c    99     67     302    3        F3    317    342    362    352
  140.            d    100    68     288    4        F4    318    343    363    353
  141.            e    101    69     274    5        F5    319    344    364    354
  142.            f    102    70     289    6        F6    320    345    365    355
  143.            g    103    71     290    7        F7    321    346    366    356
  144.            h    104    72     291    8        F8    322    347    367    357
  145.            i    105    73     279    9        F9    323    348    368    358
  146.            j    106    74     292    10       F10   324    349    369    359
  147.            k    107    75     293    11       F11   389    391    395    393
  148.            l    108    76     294    12       F12   390    392    396    394
  149.            m    109    77     306    13
  150.            n    110    78     305    14       BkSp  8      8      270    127
  151.            o    111    79     280    15       Up    328    428    408    397
  152.            p    112    80     281    16       Down  336    436    416    401
  153.            q    113    81     272    17       Left  331    431    411    371
  154.            r    114    82     275    18       Right 333    433    413    372
  155.            s    115    83     287    19       End   335    435    415    373
  156.            t    116    84     276    20       Home  327    427    407    375
  157.            u    117    85     278    21       PgUp  329    429    409    388
  158.            v    118    86     303    22       PgDn  337    437    417    374
  159.            w    119    87     273    23       Ins   338    261    418    260
  160.            x    120    88     301    24       Del   339    263    419    262
  161.            y    121    89     277    25       Tab   9      271    421    404
  162.            z    122    90     300    26       Esc   27     27     257    27
  163.                                               Enter 13     13     284    10
  164.            1 !  49     33     376    -
  165.            2 @  50     64     377    259      , <   44     60     307    -
  166.            3 #  51     35     378    -        . >   46     62     308    -
  167.            4 $  52     36     379    -        / ?   47     63     309    -
  168.            5 %  53     37     380    -        ; :   59     58     295    -
  169.            6 ^  54     94     381    30       ' "   39     34     296    -
  170.            7 &  55     38     382    -        [ {   91     123    282    27
  171.            8 *  56     42     383    -        ] }   93     125    283    29
  172.            9 (  57     40     384    -        \ |   92     124    299    28
  173.            0 )  48     41     385    -
  174.            - _  45     95     386    31
  175.            = +  61     43     387    -
  176.  
  177.  
  178.  
  179.  
  180. Keyboard & Mouse                                                             6-5
  181.  
  182. --------------------------------------------------------------------------------
  183.  
  184. Table 6.1
  185. Key Action Codes
  186. (Contd.)
  187.  
  188.            Mouse Action     Code           Window Action           Code
  189.            Left Click       513            Close Icon Selected     600
  190.            Right Click      514            Window Moved            601
  191.            Middle Click     515            Window Resized          602
  192.            Left + Right     516            Scroll Bar Up           610
  193.            Left + Middle    517            Scroll Bar Down         611
  194.            Middle + Right   518            Scroll Bar Left         612
  195.            All three        519            Scroll Bar Right        613
  196.            Left Double      523            Vertical Elevator       614
  197.            Right Double     524            Horizontal Elevator     615
  198.            Middle Double    525
  199.  
  200.            Mouse Up         584
  201.            Mouse Down       592
  202.            Mouse Left       589
  203.            Mouse Right      587
  204.  
  205.  
  206.  
  207.  
  208.          Note: the upper ASCII characters are also returned if the user holds
  209.          down the Alt key and presses the 3-digit ASCII code on the numeric
  210.          keypad, or if an international code page is active. In other words, the
  211.          input routines fully support international characters, line drawing,
  212.          and all other extended ASCII characters.
  213.  
  214.  
  215.  
  216.          In most cases, you will use the global instance Key to determine user
  217.          input. However, if you want to use an independent instance, make sure
  218.          you initialize the instance by calling the INIT method.
  219.  
  220.          The function method Extended will return true if an extended keyboard
  221.          is installed.
  222.  
  223.          Listed below is the syntax for the user input methods:
  224.  
  225.  
  226.          GetInput;
  227.  
  228.          Pauses program execution until a key or mouse button is pressed.
  229.  
  230.  
  231.          GetKey: word;
  232.  
  233.          Pauses program execution until a key or mouse button is pressed, and
  234.          returns a word value indicating the user action, (see Table 6.1)
  235.  
  236.  
  237.          LastKey: word;
  238.  
  239.  
  240.  
  241. 6-6                                                                 User's Guide
  242.  
  243. --------------------------------------------------------------------------------
  244.  
  245.          Returns a word value indicating the last user action, (see Table 6.1)
  246.  
  247.  
  248.          LastChar: char;
  249.  
  250.          If the action code of the LastKey was less than 256, the character
  251.          equivalent of the code is returned, otherwise a #0 is returned.
  252.  
  253.  
  254.          LastX: byte;
  255.  
  256.          Returns the X Coordinate of the mouse cursor when the last key action
  257.          was recorded.
  258.  
  259.  
  260.          LastY: byte;
  261.  
  262.          Returns the Y Coordinate of the mouse cursor when the last key action
  263.          was recorded.
  264.  
  265.  
  266.          DelayKey(Mills:longint);
  267.  
  268.          This function is similar to GetInput, except that the method will only
  269.          wait for Mills milliseconds. If the user is not active in the specified
  270.          period, a #0 is recorded as the last key.
  271.  
  272.  
  273.          Extended:boolean;
  274.  
  275.          This function method returns true if the system has an extended key-
  276.          board installed.
  277.  
  278.  
  279.  
  280.          The following example shows how you might pause for some user action,
  281.          and then check the pressed key to decide which routines to execute
  282.          next:
  283.  
  284.                   ...
  285.                   Key.GetInput
  286.                   case Key.LastKey of
  287.                     27:  EscapeRoutine;
  288.                     13:  EnterRoutine;
  289.                     513: LeftButtonRoutine(Key.LastX,Key.LastY);
  290.                     ...
  291.                   end; {case}
  292.                   ...
  293.  
  294.  
  295.          The following example, DEMIN1.PAS, repeatedly waits for some user
  296.          action, and displays the value of each action code:
  297.  
  298.          Program DemoInputOne;
  299.          {DEMIN1}
  300.  
  301.  
  302. Keyboard & Mouse                                                             6-7
  303.  
  304. --------------------------------------------------------------------------------
  305.  
  306.          Uses CRT,
  307.               totINPUT;
  308.  
  309.          begin
  310.             Clrscr;
  311.             Writeln('Press any key or mouse button combination.
  312.                      (Esc to quit)');
  313.             Key.SetDouble(true);
  314.             repeat
  315.                Key.GetInput;
  316.                GotoXY(1,2);
  317.                Write('You pressed key: ',Key.LastKey,'    ');
  318.             until Key.LastKey = 27;
  319.          end.
  320.  
  321.  
  322.  
  323.  
  324.  
  325.            Note: The Toolkit reports double-clicking on any of the mouse but-
  326.            tons.
  327.  
  328.            You may have used some software products which make the user
  329.            double-click the mouse at "lightning" speed. This problem occurs
  330.            because the software wants to respond as soon as possible to any
  331.            mouse activity. So, when a button is clicked, the software doesn't
  332.            wait around for very long to see if the same button has been
  333.            clicked again. If you are not quick enough, a double-click is
  334.            reported as one or two single clicks of the same button.
  335.  
  336.            The Toolkit has the same design dilemma: fast response, with
  337.            enough time so a non-athlete can double-click a button! The Tool-
  338.            kit solution is to allow you to set whether the system should wait
  339.            for a double-click. KeyOBJ includes the method SetDouble, which is
  340.            passed a boolean parameter. Pass a TRUE parameter to allow a
  341.            little extra time for double-clicks. If you don't care about
  342.            double-clicks, call SetDouble(false);. You can freely switch
  343.            between the two states throughout the program. By default, Key
  344.            does not pause for double-clicks.
  345.  
  346.            The function method GetDouble returns the current double-click
  347.            setting.
  348.  
  349.            You can experiment with the impact of the SetDouble method by
  350.            trying the above example with SetDouble enabled and disabled.
  351.  
  352.  
  353.  
  354. 6-8                                                                 User's Guide
  355.  
  356. --------------------------------------------------------------------------------
  357.  
  358. Accessing Ctrl, Alt and Shift
  359.  
  360.          KeyOBJ supports a wide variety of special key combinations like Alt-
  361.          Backspace and Ctrl-PgUp. Sometimes, however, you may want to know if
  362.          one of the shifting keys is being pressed on its own. GetInput will not
  363.          respond when Alt, Ctrl or either Shift key is pressed. It waits for a
  364.          standard alphanumeric key to be pressed.
  365.  
  366.          KeyOBJ does, however, provide the following five methods to let you
  367.          check the status of these special shifting keys:
  368.  
  369.  
  370.          AltPressed:boolean;
  371.  
  372.          Returns true if the Alt key is being held down.
  373.  
  374.  
  375.          CtrlPressed: boolean;
  376.  
  377.          Returns true if the Ctrl key is being held down.
  378.  
  379.  
  380.          LeftShiftPressed: boolean;
  381.  
  382.          Returns true if the left Shift key is being held down.
  383.  
  384.  
  385.          RightShiftPressed: boolean;
  386.  
  387.          Returns true if the right Shift key is being held down.
  388.  
  389.  
  390.          ShiftPressed: boolean;
  391.  
  392.          Returns true if either Shift key is being held down.
  393.  
  394.  
  395.          These methods are useful if you want to display an indicator which
  396.          illuminates when the special keys are pressed. The demo program,
  397.          DEMIN2.PAS, discussed in the next section, illustrates this technique.
  398.  
  399. Accessing Num, Scroll and Caps Lock
  400.  
  401.          The KeyOBJ provides the following six methods for determining and
  402.          changing the status of the Num Lock, Scroll Lock and Caps Lock keys:
  403.  
  404.  
  405.          SetCaps(On:boolean);
  406.  
  407.          Pass TRUE to turn on the Caps Lock key, or FALSE to turn it off.
  408.  
  409.  
  410.          SetNum(On:boolean);
  411.  
  412.          Pass TRUE to turn on the Num Lock key, or FALSE to turn it off.
  413.  
  414. Keyboard & Mouse                                                             6-9
  415.  
  416. --------------------------------------------------------------------------------
  417.  
  418.          SetScroll(On:boolean);
  419.  
  420.          Pass TRUE to turn on the Scroll Lock key, or FALSE to turn it off.
  421.  
  422.  
  423.          GetCaps:boolean;
  424.  
  425.          Returns TRUE if the Caps Lock is on, and FALSE if it is off.
  426.  
  427.  
  428.          GetNum:boolean;
  429.  
  430.          Returns TRUE if the Num Lock is on, and FALSE if it is off.
  431.  
  432.  
  433.          GetScroll:boolean;
  434.  
  435.          Returns TRUE if the Scroll Lock is on, and FALSE if it is off.
  436.  
  437.  
  438.  
  439.          The following demo program, DEMIN2.PAS, shows how to use the shifting
  440.          and locking keys.
  441.  
  442.          Program DemoInputTwo;
  443.          {DEMIN2}
  444.  
  445.          Uses CRT,
  446.               totINPUT, totFAST;
  447.  
  448.          begin
  449.             with Screen do
  450.             begin
  451.                 Clear(31,' ');
  452.                 PartClear(1,23,80,25,94,' ');
  453.                 WritePlain(10,5,'Press Num, Scroll, Caps Lock,
  454.                                  or hold down the Alt,');
  455.                 WritePlain(10,6,'Ctrl, Left/Right Shift keys.
  456.                                  The active keys will be');
  457.                 WritePlain(10,7,'highlighted at the foot of the
  458.                                  display.');
  459.                 WritePlain(10,9,'Any other key quits.');
  460.                 with Key do
  461.                 begin
  462.                    SetCaps(true);
  463.                    SetNum(true);
  464.                    SetScroll(true);
  465.                    repeat
  466.                       if GetCaps then
  467.                          WritePlain(40,24,'CAPS')
  468.                       else
  469.                          WritePlain(40,24,'    ');
  470.                       if GetNum then
  471.                          WritePlain(45,24,'NUM')
  472.  
  473.  
  474.  
  475. 6-10                                                                User's Guide
  476.  
  477. --------------------------------------------------------------------------------
  478.  
  479.                       else
  480.                          WritePlain(45,24,'   ');
  481.                       if GetScroll then
  482.                          WritePlain(50,24,'SCROLL')
  483.                       else
  484.                          WritePlain(50,24,'      ');
  485.                       if AltPressed then
  486.                          WritePlain(60,24,'Alt')
  487.                       else
  488.                          WritePlain(60,24,'   ');
  489.                       if CtrlPressed then
  490.                          WritePlain(65,24,'Ctrl')
  491.                       else
  492.                          WritePlain(65,24,'    ');
  493.                       if LeftShiftPressed then
  494.                          WritePlain(70,24,'L-^X')
  495.                       else
  496.                          WritePlain(70,24,'   ');
  497.                       if RightShiftPressed then
  498.                          WritePlain(75,24,'R-^X')
  499.                       else
  500.                          WritePlain(75,24,'   ');
  501.                    until KeyPressed;
  502.                    SetCaps(false);
  503.                    SetNum(false);
  504.                    SetScroll(false);
  505.                 end;
  506.             end;
  507.          end.
  508.  
  509.  
  510.  
  511.  
  512.            Note: The methods for setting and getting the status of the lock-
  513.            ing keys will only function on 100% IBM BIOS compatible systems.
  514.  
  515.  
  516.  
  517.  
  518. Setting the Keyboard Repeat Rate, and Clicking
  519.  
  520.          The PC keyboards support a typematic effect i.e. holding a key pressed
  521.          down has the same effect as pressing the key multiple times. By
  522.          default, a key must be held down for about half a second before the
  523.          repetition commences, and then about ten characters per second are
  524.          sent. Most users think this repeat rate is too slow (especially for
  525.          cursor movement) and the Toolkit provides a way of changing it.
  526.  
  527.  
  528.  
  529. Keyboard & Mouse                                                            6-11
  530.  
  531. --------------------------------------------------------------------------------
  532.  
  533.          Commencing with the IBM-AT, the ROM BIOS keyboard services provided a
  534.          way to change the typematic rate. The earliest ROM BIOS to feature
  535.          configurable typematic delays was 11/15/85. The following three KeyOBJ
  536.          methods can be used to modify the typematic rate on systems with the
  537.          required BIOS:
  538.  
  539.  
  540.          SetFast;
  541.  
  542.          Set the typematic rate to a fast 30 characters per second, i.e. there
  543.          is very little delay between repeats.
  544.  
  545.  
  546.          SetSlow;
  547.  
  548.          Sets the typematic rate to 5 characters per second.
  549.  
  550.  
  551.          SetRepeatRate(QSDelay,Rate:byte);
  552.  
  553.          This method allows you to explicitly set the typematic rate. The first
  554.          parameter accepts a value between 1 and 4, and indicates the number of
  555.          quarter seconds delay before the key commences repeating, e.g. 3 repre-
  556.          sents a 750 millisecond delay. The second parameter indicates the
  557.          repeat rate, and accepts a value between 0 and 31. The following table
  558.          shows the repeat rate parameter followed by the corresponding character
  559.          per second repeat rate:
  560.  
  561.            0   30.0    7   16.0    14  8.6     21  4.6      28  2.5
  562.            1   26.7    8   15.0    15  8.0     22  4.3      29  2.3
  563.            2   24.0    9   13.3    16  7.5     23  4.0      30  2.1
  564.            3   21.8    10  12.0    17  6.7     24  3.7      31  2.0
  565.            4   20.0    11  10.9    18  6.0     25  3.3
  566.            5   18.5    12  10.0    19  5.5     26  3.0
  567.            6   17.1    13  9.2     20  5.0     27  2.7
  568.  
  569.  
  570.          Note: keyboard ROM BIOS provides no way of determining the current
  571.          typematic rate setting.
  572.  
  573.          The typematic rate is set in BIOS, and so the methods will affect the
  574.          typematic rate for the rest of the session, even after the program has
  575.          terminated.
  576.  
  577.  
  578.  
  579.          Do you remember how typewriters used to click? Well, the Toolkit pro-
  580.          vides a way of emitting an electronic click every time a key is
  581.          pressed. The following method can be used to control keyboard clicking:
  582.  
  583.  
  584.          SetClick(On:boolean);
  585.  
  586.          Pass TRUE to activate clicking, or FALSE to switch it off. By default,
  587.          clicking is off.
  588.  
  589.  
  590. 6-12                                                                User's Guide
  591.  
  592. --------------------------------------------------------------------------------
  593.  
  594.          The demo program DEMBR1.PAS is designed to illustrate the BrowseOBJ
  595.          object which is discussed in chapter 9. There are, however, some Key
  596.          statements included. Execute the demo program and experiment with the
  597.          typematic rate.
  598.  
  599.  
  600.  
  601. Using the Keyboard Buffer
  602.  
  603.          The KeyOBJ uses an internal buffer for storing keystrokes. The sole
  604.          purpose of this buffer is to allow you to force characters into the
  605.          buffer using the methods StuffBuffer and StuffBufferStr. GetInput (and
  606.          therefore GetKey/GetChar) also checks the characters in the buffer
  607.          before checking the keyboard.
  608.  
  609.          By default, the size of the buffer is 30 characters, but this can be
  610.          easily modified by changing the StuffBufferSize constant at the top of
  611.          the totINPUT unit. Listed below is the syntax of the buffer related
  612.          methods:
  613.  
  614.  
  615.          StuffBuffer(W:word);
  616.  
  617.          This forces a key into the keyboard buffer. The parameter passed is the
  618.          word value of the character, as detailed in Table 6.1.
  619.  
  620.  
  621.          StuffBufferStr(Str:string);
  622.  
  623.          This stuffs characters (with ASCII values in the range 0 to 255) into
  624.          the keyboard buffer. This method is provided as a convenience to save
  625.          making multiple calls to StuffBuffer (one call for every character in
  626.          the string).
  627.  
  628.  
  629.          FlushBuffer;
  630.  
  631.          Erases all the keys in the keyboard buffer.
  632.  
  633.  
  634.          KeyPressed: boolean;
  635.  
  636.          Use this method in preference to Turbo Pascal's Keypressed function,
  637.          because it checks the internal buffer as well as the keyboard buffer.
  638.  
  639.  
  640.  
  641.          The keyboard stuffing capabilities form the framework for a simple but
  642.          elegant macro facility. A full example, DEMIN3.PAS, illustrates this
  643.          concept and is discussed in the next section.
  644.  
  645.  
  646.  
  647. Keyboard & Mouse                                                            6-13
  648.  
  649. --------------------------------------------------------------------------------
  650.  
  651. Assigning Keyboard Hooks
  652.  
  653.          The KeyOBJ object allows you to assign a procedure which will be called
  654.          while the program is idle and waiting for the user to press a key.
  655.          Similarly, the object allows you to assign a procedure which will be
  656.          called every time a character is pressed. These two types of procedures
  657.          are referred to as an Idle Hook and a Pressed Hook, respectively.
  658.  
  659.          IMPORTANT NOTE: If you write to the display from a hooked procedure,
  660.          you need to be aware that the active routine may have the display
  661.          window set. To avoid any problems, use the Screen method SetWinIgnore
  662.          to temporarily disable the window setting. Refer to page 5-17 for fur-
  663.          ther details.
  664.  
  665.  
  666.  
  667. Idle Hook
  668.  
  669.          An idle hook is an external procedure which will be repeatedly called
  670.          while the program is waiting for the user to input data. A good use for
  671.          an idle hook is to display a ticking clock that is always updated, or
  672.          to show the status of the "shift" and "lock" keys.
  673.  
  674.          All you have to do is create a procedure following some specific rules,
  675.          and then call the method Key.AssignIdleHook to instruct the Key object
  676.          to call your procedure.
  677.  
  678.          For a procedure to be eligible as an idle hook it must adhere to the
  679.          following three rules:
  680.  
  681.          Rule 1     The procedure must be declared as a FAR procedure. This can
  682.                     be achieved by preceding the procedure with a {$F+} compiler
  683.                     directive, and following the procedure with a {$F-} direc-
  684.                     tive. Alternatively, Turbo 6 users can use the new keyword
  685.                     FAR following the procedure statement.
  686.  
  687.          Rule 2     The procedure must be declared with no (nada/zero/none)
  688.                     passed parameters.
  689.  
  690.          Rule 3     The procedure must be at the root level, i.e. the procedure
  691.                     cannot be nested within another procedure.
  692.  
  693.          The following procedure declaration follows these rules:
  694.  
  695.                   {$F+}
  696.                   procedure MyIdleHook;
  697.                   .....{procedure statements}
  698.                   end;
  699.                   {$F-}
  700.  
  701.  
  702.          The following method AssignIdleHook is then called to instruct the
  703.          Toolkit to call your procedure while the system is waiting for input:
  704.  
  705.  
  706.  
  707.  
  708. 6-14                                                                User's Guide
  709.  
  710. --------------------------------------------------------------------------------
  711.  
  712.          AssignIdleHook(PassedProc:InputIdleProc);
  713.  
  714.          This method is passed the procedure name of a procedure declared using
  715.          the rules outlined above.
  716.  
  717.  
  718.  
  719.          Your procedure will be continually called while your program is waiting
  720.          for user input, so make sure that the procedure is compact and effi-
  721.          cient. If your procedure involves too many tasks, the program will slow
  722.          down considerably during input. If you want to call an extended task
  723.          like a background print program, you must continually check the
  724.          Key.Keypressed function method and suspend your procedure when it
  725.          returns true.
  726.  
  727.          If subsequently, you want to remove your idle hook, execute the follow-
  728.          ing:
  729.  
  730.                   Key.AssignIdleHook(NoInputIdleHook);
  731.  
  732.  
  733.  
  734.  
  735.  
  736. Pressed Hook
  737.  
  738.          A pressed hook is a procedure which is called every time a key is
  739.          pressed or a mouse button is clicked. This is particularly useful for
  740.          trapping special keys like [KEYCAP] for help, or for building keyboard
  741.          macros.
  742.  
  743.          All you have to do is create a procedure following some specific rules,
  744.          and then call the method Key.AssignPressedHook to instruct the Key
  745.          object to call your procedure each time a key is pressed.
  746.  
  747.          For a procedure to be eligible as a pressed hook it must adhere to the
  748.          following three rules:
  749.  
  750.          Rule 1     The procedure must be declared as a FAR procedure. This can
  751.                     be achieved by preceding the procedure with a {$F+} compiler
  752.                     directive, and following the procedure with a {$F-} direc-
  753.                     tive. Alternatively, Turbo 6 users can use the new keyword
  754.                     FAR following the procedure statement.
  755.  
  756.          Rule 2     The procedure must be declared with one passed parameter,
  757.                     and this parameter must be a variable parameter of type
  758.                     word, e.g. (var W:word);.
  759.  
  760.          Rule 3     The procedure must be at the root level, i.e. the procedure
  761.                     cannot be nested within another procedure.
  762.  
  763.          The following procedure declaration follows these rules:
  764.  
  765.  
  766. Keyboard & Mouse                                                            6-15
  767.  
  768. --------------------------------------------------------------------------------
  769.  
  770.                   {$F+}
  771.                   procedure MyPressedHook(var K:word);
  772.                   .....{procedure statements}
  773.                   end;
  774.                   {$F-}
  775.  
  776.  
  777.          The following method AssignPressedHook is then called to instruct the
  778.          Toolkit to call your procedure when the system receives input:
  779.  
  780.  
  781.          AssignPressedHook(PassedProc:InputPressedProc);
  782.  
  783.          This method is passed the procedure name of a procedure declared using
  784.          the rules outlined above.
  785.  
  786.  
  787.  
  788.          The parameter passed to your procedure is the value of the key (or
  789.          mouse button) just pressed, as detailed in Table 6.1. Test the value of
  790.          the parameter, and decide what action to take. As with the idle hook,
  791.          keep the hooked procedure small and efficient to avoid program execu-
  792.          tion delays.
  793.  
  794.          When your procedure terminates, the character is then processed in the
  795.          normal manner by your program. If you want the character to be ignored,
  796.          set the passed parameter value to 0. You can also use this facility to
  797.          swap the meaning of keys. For example, the following code fragment
  798.          intercepts the double-quote and replaces it with a single-quote.
  799.  
  800.                   {$F+}
  801.                   procedure DoubleGrabber(var Keycode: word);
  802.                   begin
  803.                      if KeyCode = 34 then
  804.                         KeyCode := 39;
  805.                   end;
  806.                   {$F-}
  807.  
  808.                   begin
  809.                      .....
  810.                      AssignedPressedHook(DoubleGrabber);
  811.                      .....
  812.                   end.
  813.  
  814.  
  815.          If you subsequently want to disable the pressed hook, use the following
  816.          statement:
  817.  
  818.                   Key.AssignPressedHook(NoInputPressedHook);
  819.  
  820.  
  821.  
  822. 6-16                                                                User's Guide
  823.  
  824. --------------------------------------------------------------------------------
  825.  
  826. Hook Example
  827.  
  828.          The following demo program, DEMIN3.PAS, illustrates how to use the idle
  829.          and pressed hooks, and many other KeyOBJ features:
  830.  
  831.          Program DemoInputThree;
  832.          {DEMIN3}
  833.  
  834.          Uses CRT,
  835.               totINPUT, totFAST, totMISC;
  836.  
  837.          {$F+}
  838.          procedure ClockHook;
  839.          {}
  840.          begin
  841.             with Screen do
  842.             with Key do
  843.             begin
  844.                SetWinIgnore(true);
  845.                if GetCaps then
  846.                   WritePlain(40,24,'CAPS')
  847.                else
  848.                   WritePlain(40,24,'    ');
  849.                if GetNum then
  850.                   WritePlain(45,24,'NUM')
  851.                else
  852.                   WritePlain(45,24,'   ');
  853.                if GetScroll then
  854.                   WritePlain(50,24,'SCROLL')
  855.                else
  856.                   WritePlain(50,24,'      ');
  857.                if KeyPressed then
  858.                begin
  859.                   SetWinIgnore(false);
  860.                   exit;
  861.                end;
  862.                if AltPressed then
  863.                   WritePlain(60,24,'Alt')
  864.                else
  865.                   WritePlain(60,24,'   ');
  866.                if CtrlPressed then
  867.                   WritePlain(65,24,'Ctrl')
  868.                else
  869.                   WritePlain(65,24,'    ');
  870.                if LeftShiftPressed then
  871.                   WritePlain(70,24,'L-^X')
  872.                else
  873.                   WritePlain(70,24,'   ');
  874.                if RightShiftPressed then
  875.                   WritePlain(75,24,'R-^X')
  876.  
  877.  
  878. Keyboard & Mouse                                                            6-17
  879.  
  880. --------------------------------------------------------------------------------
  881.  
  882.                else
  883.                   WritePlain(75,24,'   ');
  884.                if KeyPressed then
  885.                begin
  886.                   SetWinIgnore(false);
  887.                   exit;
  888.                end;
  889.                WritePlain(1,24,CurrentTime);
  890.                SetWinIgnore(false);
  891.             end;
  892.          end; {ClockHook}
  893.          {$F-}
  894.  
  895.          {$F+}
  896.          procedure MacroHook(var W:word);
  897.          {}
  898.          begin
  899.             case W of
  900.                286: begin
  901.                        Key.StuffBufferStr(' Apple '); {Alt-A}
  902.                        W := 0;
  903.                     end;
  904.                304: begin
  905.                        Key.StuffbufferStr(' Bravo '); {Alt-B}
  906.                        W := 0;
  907.                     end;
  908.                301: begin
  909.                        Key.StuffBuffer(27);           {Alt-X}
  910.                        W := 0;
  911.                     end;
  912.                315: begin
  913.                        Key.StuffbufferStr(' No help! '); {F1}
  914.                        W := 0;
  915.                     end;
  916.             end; {case}
  917.          end; {MacroHook}
  918.          {$F-}
  919.  
  920.          begin
  921.             with Screen do
  922.             begin
  923.                Clear(31,' ');
  924.                PartClear(1,23,80,25,94,' ');
  925.                WritePlain(5,1,'Press any alpha characters,
  926.                                or Alt-A,B for macros.
  927.                                Esc or Alt-X to quit');
  928.                GotoXY(1,3);
  929.                with Key do
  930.                begin
  931.  
  932.  
  933. 6-18                                                                User's Guide
  934.  
  935. --------------------------------------------------------------------------------
  936.  
  937.                   SetCaps(true);
  938.                   SetNum(true);
  939.                   SetScroll(true);
  940.                   AssignIdleHook(ClockHook);
  941.                   AssignPressedHook(MacroHook);
  942.                   Repeat
  943.                       GetInput;
  944.                       Write(LastChar);
  945.                   Until LastKey = 27;
  946.                   SetCaps(false);
  947.                   SetNum(false);
  948.                   SetScroll(false);
  949.                end;
  950.             end;
  951.          end.
  952.  
  953.  
  954.  
  955. Using the Mouse
  956.  
  957.          The Toolkit provides full mouse support, and any mouse activity is
  958.          reported by the KeyOBJ object. Normally, you will not need to access
  959.          the mouse directly, but in case you need to, the totINPUT unit includes
  960.          the global instance MOUSE of type MouseOBJ. This instance can be used
  961.          to control the mouse cursor and check the status of the mouse buttons.
  962.  
  963.          All the Toolkit mouse support is for text mode only - the Toolkit does
  964.          not support the mouse in graphics mode.
  965.  
  966.          The following methods can be used to control the mouse cursor and check
  967.          the mouse status:
  968.  
  969.  
  970.          Installed: boolean;
  971.  
  972.          Returns true if a mouse and mouse driver are installed.
  973.  
  974.  
  975.          Visible: boolean;
  976.  
  977.          Returns true if the mouse cursor is visible on the display.
  978.  
  979.  
  980.          Hide;
  981.  
  982.          Hides the mouse cursor.
  983.  
  984.  
  985.          Show;
  986.  
  987.          Displays the mouse cursor.
  988.  
  989.  
  990.          Move(X,Y:integer);
  991.  
  992.  
  993.  
  994. Keyboard & Mouse                                                            6-19
  995.  
  996. --------------------------------------------------------------------------------
  997.  
  998.          Moves the mouse cursor to the coordinates (X,Y). Note this command
  999.          ignores the current window setting.
  1000.  
  1001.  
  1002.          Confine(X1,Y1,X2,Y2:byte);
  1003.  
  1004.          Restricts the mouse so that it can only move within the coordinates
  1005.          (X1,Y1) to (X2,Y2).
  1006.  
  1007.  
  1008.          Location(var X,Y:byte);
  1009.  
  1010.          Updates the variables X and Y with the current location coordinates of
  1011.          the mouse.
  1012.  
  1013.  
  1014.          Status(var L,C,R:boolean; var X,Y);
  1015.  
  1016.          Updates the L,C,R boolean variables to true if any of the Left, Center,
  1017.          or Right mouse buttons are depressed, and updates the variables X and Y
  1018.          with the current mouse location.
  1019.  
  1020.  
  1021.          Pressed(Button:integer; var X,Y:byte): byte;
  1022.  
  1023.          Returns the number of times the specified button has been pressed since
  1024.          the function was last called. Button values of 0,1 and 2 represent the
  1025.          Left, Right and Center buttons respectively. The variables X and Y are
  1026.          updated with the coordinates of the mouse the last time the button was
  1027.          pressed.
  1028.  
  1029.  
  1030.          Released(Button:integer; var X,Y:byte):byte;
  1031.  
  1032.          Returns the number of times the specified button has been released
  1033.          since the function was last called. Button values of 0,1 and 2 repre-
  1034.          sent the Left, Right and Center buttons respectively. The variables X
  1035.          and Y are updated with the coordinates of the mouse the last time the
  1036.          button was released.
  1037.  
  1038.  
  1039.          GetButtons: byte;
  1040.  
  1041.          Returns the number of buttons installed on the mouse.
  1042.  
  1043.  
  1044.          SetMouseCursorStyle(OrdChar,Attr:byte);
  1045.  
  1046.          Sets the mouse cursor to the character represented by the ASCII value
  1047.          OrdChar. The second parameter controls the display attribute of the
  1048.          mouse cursor. If a zero is specified, the Toolkit uses the standard
  1049.          mouse device driver technique, which changes color based on the under-
  1050.          lying screen attribute to ensure maximum contrast. If a non-zero
  1051.          attribute value is specified, the mouse cursor will be displayed in the
  1052.          specified attribute regardless of the screen display attributes.
  1053.  
  1054.  
  1055. 6-20                                                                User's Guide
  1056.  
  1057. --------------------------------------------------------------------------------
  1058.  
  1059.          SetLeft(On:boolean);
  1060.  
  1061.          The de facto standard in the industry is for the left button to be the
  1062.          "do it" or "enter" button, and this is the Toolkit default. Use the
  1063.          method SetLeft to control whether the left button or the right button
  1064.          is used as the action button. Pass a TRUE parameter to use the left, or
  1065.          a FALSE parameter to use the right.
  1066.  
  1067.  
  1068.          Reset;
  1069.  
  1070.          This method calls the mouse reset interrupt. The mouse is set back to
  1071.          the center of the display, the cursor style is set back to the default,
  1072.          and the mouse cursor is hidden.
  1073.  
  1074.  
  1075.  
  1076.          Listed below is the mouse demo program DEMIN4.PAS, followed by figure
  1077.          6.1 which illustrates the output from the program.
  1078.  
  1079.          Program DemoInputFour;
  1080.          {DEMIN4}
  1081.  
  1082.          Uses CRT,
  1083.               totINPUT, totFAST, totSTR;
  1084.  
  1085.          Var
  1086.            Ch : char;
  1087.            L,C,R,OldL,OldC,OldR: boolean;
  1088.            X,Y,OldX,OldY: byte;
  1089.  
  1090.          begin
  1091.             Clrscr;
  1092.             with Mouse do
  1093.             begin
  1094.                if not Installed then
  1095.                begin
  1096.                   Writeln('This demo will only function
  1097.                            on systems equipped with a mouse');
  1098.                end
  1099.                else
  1100.                begin
  1101.                   WriteLn('You have a ',GetButtons,' button mouse!');
  1102.                   Writeln('Press: C to confine the mouse');
  1103.                   Writeln('       U to unconfine the mouse');
  1104.                   Writeln('       L to change the mouse cursor');
  1105.                   Writeln('       R to reset mouse');
  1106.                   Writeln('       H to hide the mouse');
  1107.                   Writeln('       S to show the mouse');
  1108.                   Writeln('       any mouse button');
  1109.                   Writeln('       Esc to quit');
  1110.                   Screen.FillBox(15,10,65,20,30,1);
  1111.                   Show;
  1112.  
  1113. Keyboard & Mouse                                                            6-21
  1114.  
  1115. --------------------------------------------------------------------------------
  1116.  
  1117.                   repeat
  1118.                      with Screen do
  1119.                      repeat
  1120.                         Status(L,C,R,X,Y);
  1121.                         if OldL <> L then
  1122.                            if L then
  1123.                               WriteAT(20,11,30,'Left Button')
  1124.                            else
  1125.                               WriteAT(20,11,30,'           ');
  1126.                         if OldR <> R then
  1127.                            if R then
  1128.                               WriteAT(20,12,30,'Right Button')
  1129.                            else
  1130.                               WriteAT(20,12,30,'            ');
  1131.                         if OldC <> C then
  1132.                            if C then
  1133.                               WriteAT(20,13,30,'Middle Button')
  1134.                            else
  1135.                               WriteAT(20,13,30,'             ');
  1136.                         if OldX <> X then
  1137.                            WriteAT(20,15,30,inttostr(X)+' ');
  1138.                         if OldY <> Y then
  1139.                             WriteAT(20,16,30,inttostr(Y)+' ');
  1140.                         OldL := L;
  1141.                         OldR := R;
  1142.                         OldC := C;
  1143.                         OldX := X;
  1144.                         OldY := Y;
  1145.                      until Key.KeyPressed;
  1146.                      Key.GetInput;
  1147.                      case upcase(Key.LastChar) of
  1148.                         'C': Confine(15,10,65,20);
  1149.                         'U': Confine(1,1,80,25);
  1150.                         'L': SetMouseCursorStyle(random(200)+56,0);
  1151.                         'H': Hide;
  1152.                         'S': Show;
  1153.                         'R': begin
  1154.                                 Hide;
  1155.                                 Reset;
  1156.                                 Show;
  1157.                              end;
  1158.                      end; {case}
  1159.                   until Key.LastKey = 27;
  1160.                   Hide;
  1161.                end;
  1162.                GotoXY(1,23);
  1163.             end;
  1164.          end.
  1165.  
  1166.  
  1167.  
  1168. 6-22                                                                User's Guide
  1169.  
  1170. --------------------------------------------------------------------------------
  1171.  
  1172. Figure 6.1                                                              [SCREEN]
  1173. Using the
  1174. MOUSE Object
  1175.