home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / basic / mlib30 / mlibtool.bas < prev    next >
Encoding:
BASIC Source File  |  1994-02-21  |  17.3 KB  |  480 lines

  1.  DEFINT A-Z
  2.  '============================= MLIBTOOL.BAS ================================
  3.  '             Copyright (C) 1994 Terry Venn. All rights reserved.
  4.  '
  5.  '                  THIS SAMPLE PROGRAM IS PROVIDED AS IS.
  6.  '
  7.  ' You may modify/use this code in any way you wish, provided that you agree
  8.  ' that Terry Venn has no warranties, obligations or liabilities for any code
  9.  ' contained in this sample program.
  10.  '
  11.  ' Optional (mouse event handler) BASIC routines.
  12.  '
  13.  ' The MLIB Mouse Toolkit includes:
  14.  '
  15.  ' InMouseState()       - Returns status of the mouse event handler.
  16.  '
  17.  ' GetDblClkSettings()  - Returns double-click settings.
  18.  ' SetDblClkSettings()  - Sets double-click settings.
  19.  '
  20.  ' GetEventMask()       - Returns current event mask (events being trapped).
  21.  ' SetEventMask()       - Sets current event mask.
  22.  '
  23.  ' GetEventsPending()   - Returns number of events pending in buffer.
  24.  '
  25.  ' InMouseSave()        - Save event handler's state.
  26.  '
  27.  ' InMouseRestore()     - Restore event handler's state.
  28.  '
  29.  ' NOTE: The following procedures are considered as 'sample routines' only,
  30.  '       as they serve no real purpose in this library.
  31.  '
  32.  ' GetHeadPtr()         - Position of head pointer in the event buffer.
  33.  ' GetTailPtr()         - Position of tail pointer in the event buffer.
  34.  ' ClearEventBuffer()   - Clear events pending in the buffer.
  35.  '
  36.  ' QB refers to: QuickBasic 4.5
  37.  ' VBDOS refers to: Visual Basic for DOS
  38.  '
  39.  ' To add the mouse toolkit routines to MLIBN, and create a new QB quick
  40.  ' library:
  41.  '
  42.  ' BC   MLIBTOOL.BAS;
  43.  ' LIB  MLIBN.LIB + MLIBTOOL.OBJ;
  44.  ' LINK /Q MLIBN.LIB, MLIBN.QLB,, BQLB45.LIB;
  45.  '
  46.  ' To add the mouse toolkit routines to MLIBF, and create a new VBDOS quick
  47.  ' library:
  48.  '
  49.  ' BC   MLIBTOOL.BAS;
  50.  ' LIB  MLIBF.LIB + MLIBTOOL.OBJ;
  51.  ' LINK /Q MLIBF.LIB, MLIBF.QLB,, VBDOSQLB.LIB;
  52.  '
  53.  ' QuickBasic and Visual Basic are trademarks of Microsoft Corporation.
  54.  '===========================================================================
  55.  '
  56.  ' Some tech notes.
  57.  '
  58.  ' Event handler's data block.
  59.  ' Function, InMouseAddress() (contained in library) returns a pointer to the
  60.  ' beginning of this block.
  61.  '
  62.  ' ┌─ 28 bytes ─┬──────── 14 bytes ─────────┬──── 90 bytes ───┐
  63.  ' ┌───┬──  ┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬─  ──┬───┐ End of
  64.  ' └───┴  ──┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴  ───┴───┘ buffer.
  65.  '   │        │   │   │   │   │   │   │   │   └── Buffer (start).
  66.  '   │        │   │   │   │   │   │   │   └────── Tail pointer.
  67.  '   │        │   │   │   │   │   │   └────────── Head pointer.
  68.  '   │        │   │   │   │   │   └────────────── Double-click height.
  69.  '   │        │   │   │   │   └────────────────── Double-click width.
  70.  '   │        │   │   │   └────────────────────── Double-click speed.
  71.  '   │        │   │   └────────────────────────── Event mask.
  72.  '   │        │   └────────────────────────────── Status flag.
  73.  '   └────────┴────────────────────────────────── Internal use only.
  74.  '
  75.  ' The event handler uses what is called a circular buffer. In this buffer,
  76.  ' mouse events are stored, up to a maximum of eight. When an event is placed
  77.  ' in the buffer, it is written to the position the tail pointer points to,
  78.  ' then the tail advances to the next positon. If the tail is one event (10
  79.  ' bytes) behind the head, then the buffer is full. Likewise, when reading,
  80.  ' the head points to the event that will be read, and then advances to next
  81.  ' position. When the head wraps around and catches up to the tail, the
  82.  ' buffer is then empty, at this point, the head and tail are equal.
  83.  '
  84.  ' Worth noting, the mouse event handler is capable of detecting buffer over-
  85.  ' flows (see below). The handler will generate and place a release event
  86.  ' for each overflow in the buffer when there is enough free space to do so.
  87.  ' When a release event is generated, due to an overflow, the current pointer
  88.  ' position is used, not the position where the actual lost event occurred.
  89.  ' The reason for this is to eliminate the risk of your code appearing to
  90.  ' hang when a release event is missed.
  91.  '
  92.  ' Example:
  93.  '
  94.  ' DO
  95.  ' .  If a left button overflow occurred inside this loop, it would
  96.  ' .  continuously loop, or loop until the next button up event occurred.
  97.  ' .
  98.  '
  99.  ' LOOP UNTIL MouseEvent% AND LButtonUp
  100.  '
  101.  ' Buffer overflow - when one or more button presses fill the event buffer
  102.  ' leaving no space for when the buttons are released. An overflow can occur
  103.  ' when your program is doing something that requires a large amount of
  104.  ' computing time, and is unable to poll InMouse() to remove events from the
  105.  ' buffer.
  106.  '
  107.  ' IMPORTANT: Be carefull when POKE-ing around, altering the first 28 bytes,
  108.  '            the status flag, head, and tail pointer, will produce
  109.  '            unpredictable results, and may lead to system failure. You may
  110.  '            change the event mask, and double-click default settings
  111.  '            without risk of crashing the system.
  112.  '
  113.  '===========================================================================
  114.  '
  115.  ' Each mouse event placed in the buffer, consists of the following:
  116.  '
  117.  ' ┌────────────── 10 bytes ───────────────┐
  118.  ' ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
  119.  ' └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
  120.  '   └─┬─┘   └─┬─┘   └─┬─┘   └─┬─┘   └─┬─┘
  121.  '     │       │       │       │       └──── Vertical pointer position.
  122.  '     │       │       │       └──────────── Horizontal pointer position.
  123.  '     │       │       └──────────────────── Event bit-field.
  124.  '     │       └──────────────────────────── Low  word of time stamp.
  125.  '     └──────────────────────────────────── High word of time stamp.
  126.  '
  127.  ' The InMouse() function returns:
  128.  '
  129.  ' MouseEvent% = InMouse(MouseX%, MouseY%)
  130.  '
  131.  ' 1. Event bit-field (MouseEvent%).
  132.  ' 2. Horizontal pointer position (MouseX%).
  133.  ' 3. Vertical pointer position (MouseY%).
  134.  '
  135.  ' The time-stamp data is not returned (time the event occurred).
  136.  '
  137.  '===========================================================================
  138.  
  139.  '$INCLUDE: 'MLIB.BI'
  140.  
  141.  ' Space for handler's state.
  142.  TYPE BufferType
  143.      Buffer AS STRING * 132
  144.  END TYPE
  145.  
  146.  DIM SHARED SaveState AS BufferType
  147.  
  148. '============================================================================
  149. ' Clear the mouse event buffer by setting the head to equal the tail.
  150. '
  151. ' NOTE, this is just a sample routine and is not meant to be used.
  152. '       Use MLIB's InMouseHandler(ClearBuffer) to clear buffer and zero
  153. '       internal data.
  154. ' Uses:
  155. '       InMouseAddress() - Returns segment:offset to handler's data area.
  156. '       GetWord()        - Peek two bytes.
  157. '       PutWord()        - Poke two bytes.
  158. '============================================================================
  159. SUB ClearEventBuffer
  160.  
  161.  ' Get address of handler's data block.
  162.  S% = InMouseAddress(O%)                ' S% = Segment, O% = Offset.
  163.  
  164.  T% = GetWord(S%, O% + TailPtrOff)      ' Get tail position.
  165.  
  166.  CALL PutWord(S%, O% + HeadPtrOff, T%)  ' Set head to equal tail.
  167.  
  168. END SUB
  169.  
  170. '============================================================================
  171. ' Returns double-click settings.
  172. '
  173. ' ClickS% - Time frame in which a double-click will be registered.
  174. '
  175. ' ClickW% - Specifies the width (in pixels, on either side) that the pointer
  176. '           can move between clicks when double-clicking.
  177. '
  178. ' ClickH% - Specifies the height (in pixels, above and below) that the
  179. '           pointer can move between clicks when double-clicking.
  180. '============================================================================
  181. SUB GetDblClkSettings (ClickS%, ClickW%, ClickH%)
  182.  
  183.  ' Get address of handler's data block.
  184.  S% = InMouseAddress(O%)                        ' S% = Segment, O% = Offset.
  185.  
  186.  ' Get double-click data.
  187.  ClickS% = GetWord(S%, O% + ClickSOff)          ' Peek at click speed.
  188.  ClickW% = GetWord(S%, O% + ClickWOff)          ' Peek at click width.
  189.  ClickH% = GetWord(S%, O% + ClickHOff)          ' Peek at click height.
  190.  
  191. END SUB
  192.  
  193. '============================================================================
  194. ' Returns the current event mask (mouse events currently being captured).
  195. '
  196. ' ' Determine which events are currently being trapped.
  197. ' IF OldMask% AND MouseMoved THEN               ' Decimal: 1
  198. '    ' We are trapping mouse movement.
  199. ' ELSEIF OldMask% AND LButtonDown THEN          ' Decimal: 2
  200. '    ' We are trapping left button presses.
  201. ' ELSEIF OldMask% AND LButtonUp THEN            ' Decimal: 4
  202. '    ' We are trapping left button releases.
  203. ' .
  204. ' . \_ Other tests.
  205. ' . /
  206. '
  207. ' END IF
  208. '
  209. '============================================================================
  210. SUB GetEventMask (OldMask%)
  211.  
  212.  ' Get address of handler's data block.
  213.  S% = InMouseAddress(O%)                        ' S% = Segment, O% = Offset.
  214.  
  215.  ' Get event mask flags.
  216.  OldMask% = GetWord(S%, O% + EventMaskOff)
  217.  
  218. END SUB
  219.  
  220. '============================================================================
  221. ' Returns the number of events pending in the mouse event buffer.
  222. '============================================================================
  223. FUNCTION GetEventsPending
  224.  
  225.  T% = GetTailPtr                        ' Get tail position.
  226.  H% = GetHeadPtr                        ' Get head position.
  227.   
  228.  N% = T% - H%                           ' Subtract head from tail
  229.  
  230.  BufferLen% = 90                        ' Length of mouse event buffer.
  231.  RecordLen% = 10                        ' Length of each mouse event.
  232.  
  233.  IF N% < 0 THEN                         ' If the head pointer is
  234.     N% = N% + BufferLen%                ' greater than the tail,
  235.  END IF                                 ' wrap around.
  236.  
  237.  N% = N% \ RecordLen%                   ' Divide by the length of one event
  238.                                         ' to get the actual value.
  239.  GetEventsPending = N%
  240.  
  241. END FUNCTION
  242.  
  243. '============================================================================
  244. ' Returns the head pointer's position in the event buffer.
  245. '============================================================================
  246. FUNCTION GetHeadPtr
  247.  
  248.  ' Get address of handler's data block.
  249.  S% = InMouseAddress(O%)                ' S% = Segment, O% = Offset.
  250.  
  251.  H% = GetWord(S%, O% + HeadPtrOff)      ' Get the value.
  252.  
  253.  ' Convert head pointer position relative to the first byte in the buffer.
  254.  ' If you were to write a block of data to the buffer, S%:H% holds the actual
  255.  ' head pointer's position.  We must also subtract the distance from the
  256.  ' beginning of the handler's data block to the first byte of the buffer.
  257.  
  258.  GetHeadPtr = H% - O% - BufferOff       ' Return value.
  259.  
  260. END FUNCTION
  261.  
  262. '============================================================================
  263. ' Returns the tail pointer's position in the event buffer.
  264. '============================================================================
  265. FUNCTION GetTailPtr
  266.  
  267.  ' Get address of handler's data block.
  268.  S% = InMouseAddress(O%)                ' S% = Segment, O% = Offset.
  269.  
  270.  T% = GetWord(S%, O% + TailPtrOff)      ' Get the value.
  271.  
  272.  ' Convert tail pointer position relative to the first byte in the buffer.
  273.  ' If you were to write a block of data to the buffer, S%:H% holds the actual
  274.  ' tail pointer's position.  We must also subtract the distance from the
  275.  ' beginning of the handler's data block to the first byte of the buffer.
  276.  
  277.  GetTailPtr = T% - O% - BufferOff       ' Return value.
  278.  
  279. END FUNCTION
  280.  
  281. '============================================================================
  282. ' Restore handler's state
  283. '
  284. ' You must use InMouseSave() to save the handler's state first.
  285. '
  286. ' Buffer$: Holds handler's state (data block).
  287. '
  288. ' NOTE, the mouse event handler state is restored, not mouse driver state.
  289. '============================================================================
  290. '
  291. SUB InMouseRestore (Buffer$)
  292.  
  293.  ' Make sure buffer is the correct length.
  294.  IF LEN(Buffer$) <> 132 THEN EXIT SUB
  295.  
  296.  ' Get status of handler.
  297.  OldStatus% = InMouseState
  298.  
  299.  ' Disable before restoring state.
  300.  CALL InMouseHandler(EventDisable)
  301.  
  302.  ' Point to handler's data area.
  303.  S% = InMouseAddress(O%)                        ' S% = Segment, O% = Offset.
  304.  
  305.  ' Load fixed string with state.
  306.  SaveState.Buffer = Buffer$
  307.  
  308.  ' Buffer pointer.
  309.  BufSeg% = VARSEG(SaveState.Buffer)
  310.  BufOff% = VARPTR(SaveState.Buffer)
  311.  
  312.  ' Restore handler's complete data block (132 bytes).
  313.  FOR Address% = 0 TO 132 - 2 STEP 2
  314.  
  315.     ' Get data from buffer.
  316.     Value% = GetWord(BufSeg%, BufOff% + Address%)
  317.    
  318.     ' Place data back in handler's data block.
  319.     CALL PutWord(S%, O% + Address%, Value%)
  320.  
  321.  NEXT Address%
  322.  
  323.  ' If handler was active upon entry.
  324.  IF OldStatus% AND EventEnable THEN
  325.     CALL InMouseHandler(EventEnable)
  326.  END IF
  327.  
  328. END SUB
  329.  
  330. '============================================================================
  331. ' Save handler's state, store in Buffer$.
  332. '
  333. ' NOTE, the mouse event handler state is saved, not the mouse driver state.
  334. '============================================================================
  335. SUB InMouseSave (Buffer$)
  336.  
  337.  ' Get status of handler.
  338.  OldStatus% = InMouseState
  339.  
  340.  ' Disable before saving state.
  341.  CALL InMouseHandler(EventDisable)
  342.  
  343.  ' Point to handler's data area.
  344.  S% = InMouseAddress(O%)                        ' S% = Segment, O% = Offset.
  345.  
  346.  ' Buffer pointer.
  347.  BufSeg% = VARSEG(SaveState.Buffer)
  348.  BufOff% = VARPTR(SaveState.Buffer)
  349.  
  350.  ' Save handler's complete data block (132 bytes).
  351.  FOR Address% = 0 TO 132 - 2 STEP 2
  352.  
  353.     ' Get data.
  354.     Value% = GetWord(S%, O% + Address%)
  355.  
  356.     ' Store data in buffer.
  357.     CALL PutWord(BufSeg%, BufOff% + Address%, Value%)
  358.  
  359.  NEXT Address%
  360.  
  361.  ' Return state to caller.
  362.  Buffer$ = SaveState.Buffer
  363.  
  364.  ' If handler was active upon entry.
  365.  IF OldStatus% AND EventEnable THEN
  366.     CALL InMouseHandler(EventEnable)
  367.  END IF
  368.  
  369. END SUB
  370.  
  371. '============================================================================
  372. ' Return the mouse event handler's status.
  373. '
  374. ' Status% = InMouseState
  375. '
  376. ' ' Determine status.
  377. ' IF Status% = 0 THEN
  378. '    Status$ = "Not Installed"
  379. ' ELSEIF Status% AND EventEnable THEN   ' Decimal: 2
  380. '    Status$ = "Enabled"
  381. ' ELSEIF Status% AND EventDisable THEN  ' Decimal: 4
  382. '    Status$ = "Disabled"
  383. ' END IF
  384. '
  385. '============================================================================
  386. FUNCTION InMouseState
  387.  
  388.  ' Get address of handler's data block.
  389.  S% = InMouseAddress(O%)                        ' S% = Segment, O% = Offset.
  390.  
  391.  ' Get the current status of event handler.
  392.  InMouseState = GetWord(S%, O% + InMouseStateOff)
  393.  
  394. END FUNCTION
  395.  
  396. '============================================================================
  397. ' Set double-click settings.
  398. '
  399. ' ClickS% - Time frame in which a double-click will be registered.
  400. '
  401. ' ClickW% - Specifies the width (in pixels, on either side) that the pointer
  402. '           can move between clicks when double-clicking.
  403. '
  404. ' ClickH% - Specifies the height (in pixels, above and below) that the
  405. '           pointer can move between clicks when double-clicking.
  406. '============================================================================
  407. SUB SetDblClkSettings (ClickS%, ClickW%, ClickH%)
  408.  
  409.  ' Get address of handler's data block.
  410.  S% = InMouseAddress(O%)                        ' S% = Segment, O% = Offset.
  411.  
  412.  ' Change double-click settings.
  413.  CALL PutWord(S%, O% + ClickSOff, ClickS%)      ' Set double-click speed.
  414.  CALL PutWord(S%, O% + ClickWOff, ClickW%)      ' Set double-click width.
  415.  CALL PutWord(S%, O% + ClickHOff, ClickH%)      ' Set double-click height.
  416.  
  417. END SUB
  418.  
  419. '============================================================================
  420. ' Specify which mouse events the handler will capture.
  421. '
  422. ' By default, the event handler captures the following events:
  423. '
  424. ' 1. All button events (presses and releases).
  425. ' 2. Double-clicking for all buttons.
  426. ' 3. Shift-state events (cannot be disabled).
  427. '
  428. ' Use following table to build your own event trapping mask.
  429. '
  430. ' Event:                 Turn On:  Turn Off:
  431. ' ═════════════════════  ════════  ═════════
  432. ' Mouse Movement         1         -2
  433. ' Left Button Press      2         -3
  434. ' Left Button Release    4         -5
  435. ' Right Button Press     8         -9
  436. ' Right Button Release   16        -17
  437. ' Center Button Press    32        -33
  438. ' Center Button Release  64        -65
  439. ' ──────────────────────────────────────────
  440. '
  441. ' To trap left button press and release:
  442. '
  443. ' NewMask% = LButtonDown OR LButtonUp: CALL SetEventMask (NewMask%)
  444. '
  445. ' To turn off an event currently being captured:
  446. '
  447. ' ' Mask out mouse movement.
  448. ' NewMask% = NewMask% AND -2: CALL SetEventMask (NewMask%)
  449. '
  450. ' ' Or use the NOT operator.
  451. ' NewMask% = NewMask% AND NOT 1: CALL SetEventMask (NewMask%)
  452. '
  453. ' NOTE: The default for double-clicking is on. To turn this feature off, set
  454. '       the double-click speed to zero. See: SUB SetDblClkSettings().
  455. '
  456. '============================================================================
  457. SUB SetEventMask (NewMask%)
  458.  
  459.  ' Get status of handler.
  460.  OldStatus% = InMouseState
  461.  
  462.  ' Disable the handler first.
  463.  CALL InMouseHandler(EventDisable)
  464.  
  465.  ' Get address of handler's data block.
  466.  S% = InMouseAddress(O%)                ' S% = Segment, O% = Offset.
  467.  
  468.  ' Change event mask flags.
  469.  CALL PutWord(S%, O% + EventMaskOff, NewMask%)
  470.  
  471.  ' We must enable handler before the
  472.  ' new event mask will take effect.
  473.  ' If handler was active upon entry.
  474.  IF OldStatus% AND EventEnable THEN
  475.     CALL InMouseHandler(EventEnable)
  476.  END IF
  477.  
  478. END SUB
  479.  
  480.