home *** CD-ROM | disk | FTP | other *** search
- DEFINT A-Z
- '============================= MLIBTOOL.BAS ================================
- ' Copyright (C) 1994 Terry Venn. All rights reserved.
- '
- ' THIS SAMPLE PROGRAM IS PROVIDED AS IS.
- '
- ' You may modify/use this code in any way you wish, provided that you agree
- ' that Terry Venn has no warranties, obligations or liabilities for any code
- ' contained in this sample program.
- '
- ' Optional (mouse event handler) BASIC routines.
- '
- ' The MLIB Mouse Toolkit includes:
- '
- ' InMouseState() - Returns status of the mouse event handler.
- '
- ' GetDblClkSettings() - Returns double-click settings.
- ' SetDblClkSettings() - Sets double-click settings.
- '
- ' GetEventMask() - Returns current event mask (events being trapped).
- ' SetEventMask() - Sets current event mask.
- '
- ' GetEventsPending() - Returns number of events pending in buffer.
- '
- ' InMouseSave() - Save event handler's state.
- '
- ' InMouseRestore() - Restore event handler's state.
- '
- ' NOTE: The following procedures are considered as 'sample routines' only,
- ' as they serve no real purpose in this library.
- '
- ' GetHeadPtr() - Position of head pointer in the event buffer.
- ' GetTailPtr() - Position of tail pointer in the event buffer.
- ' ClearEventBuffer() - Clear events pending in the buffer.
- '
- ' QB refers to: QuickBasic 4.5
- ' VBDOS refers to: Visual Basic for DOS
- '
- ' To add the mouse toolkit routines to MLIBN, and create a new QB quick
- ' library:
- '
- ' BC MLIBTOOL.BAS;
- ' LIB MLIBN.LIB + MLIBTOOL.OBJ;
- ' LINK /Q MLIBN.LIB, MLIBN.QLB,, BQLB45.LIB;
- '
- ' To add the mouse toolkit routines to MLIBF, and create a new VBDOS quick
- ' library:
- '
- ' BC MLIBTOOL.BAS;
- ' LIB MLIBF.LIB + MLIBTOOL.OBJ;
- ' LINK /Q MLIBF.LIB, MLIBF.QLB,, VBDOSQLB.LIB;
- '
- ' QuickBasic and Visual Basic are trademarks of Microsoft Corporation.
- '===========================================================================
- '
- ' Some tech notes.
- '
- ' Event handler's data block.
- ' Function, InMouseAddress() (contained in library) returns a pointer to the
- ' beginning of this block.
- '
- ' ┌─ 28 bytes ─┬──────── 14 bytes ─────────┬──── 90 bytes ───┐
- ' ┌───┬── ┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬─ ──┬───┐ End of
- ' └───┴ ──┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴ ───┴───┘ buffer.
- ' │ │ │ │ │ │ │ │ │ └── Buffer (start).
- ' │ │ │ │ │ │ │ │ └────── Tail pointer.
- ' │ │ │ │ │ │ │ └────────── Head pointer.
- ' │ │ │ │ │ │ └────────────── Double-click height.
- ' │ │ │ │ │ └────────────────── Double-click width.
- ' │ │ │ │ └────────────────────── Double-click speed.
- ' │ │ │ └────────────────────────── Event mask.
- ' │ │ └────────────────────────────── Status flag.
- ' └────────┴────────────────────────────────── Internal use only.
- '
- ' The event handler uses what is called a circular buffer. In this buffer,
- ' mouse events are stored, up to a maximum of eight. When an event is placed
- ' in the buffer, it is written to the position the tail pointer points to,
- ' then the tail advances to the next positon. If the tail is one event (10
- ' bytes) behind the head, then the buffer is full. Likewise, when reading,
- ' the head points to the event that will be read, and then advances to next
- ' position. When the head wraps around and catches up to the tail, the
- ' buffer is then empty, at this point, the head and tail are equal.
- '
- ' Worth noting, the mouse event handler is capable of detecting buffer over-
- ' flows (see below). The handler will generate and place a release event
- ' for each overflow in the buffer when there is enough free space to do so.
- ' When a release event is generated, due to an overflow, the current pointer
- ' position is used, not the position where the actual lost event occurred.
- ' The reason for this is to eliminate the risk of your code appearing to
- ' hang when a release event is missed.
- '
- ' Example:
- '
- ' DO
- ' . If a left button overflow occurred inside this loop, it would
- ' . continuously loop, or loop until the next button up event occurred.
- ' .
- '
- ' LOOP UNTIL MouseEvent% AND LButtonUp
- '
- ' Buffer overflow - when one or more button presses fill the event buffer
- ' leaving no space for when the buttons are released. An overflow can occur
- ' when your program is doing something that requires a large amount of
- ' computing time, and is unable to poll InMouse() to remove events from the
- ' buffer.
- '
- ' IMPORTANT: Be carefull when POKE-ing around, altering the first 28 bytes,
- ' the status flag, head, and tail pointer, will produce
- ' unpredictable results, and may lead to system failure. You may
- ' change the event mask, and double-click default settings
- ' without risk of crashing the system.
- '
- '===========================================================================
- '
- ' Each mouse event placed in the buffer, consists of the following:
- '
- ' ┌────────────── 10 bytes ───────────────┐
- ' ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
- ' └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘
- ' └─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘ └─┬─┘
- ' │ │ │ │ └──── Vertical pointer position.
- ' │ │ │ └──────────── Horizontal pointer position.
- ' │ │ └──────────────────── Event bit-field.
- ' │ └──────────────────────────── Low word of time stamp.
- ' └──────────────────────────────────── High word of time stamp.
- '
- ' The InMouse() function returns:
- '
- ' MouseEvent% = InMouse(MouseX%, MouseY%)
- '
- ' 1. Event bit-field (MouseEvent%).
- ' 2. Horizontal pointer position (MouseX%).
- ' 3. Vertical pointer position (MouseY%).
- '
- ' The time-stamp data is not returned (time the event occurred).
- '
- '===========================================================================
-
- '$INCLUDE: 'MLIB.BI'
-
- ' Space for handler's state.
- TYPE BufferType
- Buffer AS STRING * 132
- END TYPE
-
- DIM SHARED SaveState AS BufferType
-
- '============================================================================
- ' Clear the mouse event buffer by setting the head to equal the tail.
- '
- ' NOTE, this is just a sample routine and is not meant to be used.
- ' Use MLIB's InMouseHandler(ClearBuffer) to clear buffer and zero
- ' internal data.
- ' Uses:
- ' InMouseAddress() - Returns segment:offset to handler's data area.
- ' GetWord() - Peek two bytes.
- ' PutWord() - Poke two bytes.
- '============================================================================
- SUB ClearEventBuffer
-
- ' Get address of handler's data block.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- T% = GetWord(S%, O% + TailPtrOff) ' Get tail position.
-
- CALL PutWord(S%, O% + HeadPtrOff, T%) ' Set head to equal tail.
-
- END SUB
-
- '============================================================================
- ' Returns double-click settings.
- '
- ' ClickS% - Time frame in which a double-click will be registered.
- '
- ' ClickW% - Specifies the width (in pixels, on either side) that the pointer
- ' can move between clicks when double-clicking.
- '
- ' ClickH% - Specifies the height (in pixels, above and below) that the
- ' pointer can move between clicks when double-clicking.
- '============================================================================
- SUB GetDblClkSettings (ClickS%, ClickW%, ClickH%)
-
- ' Get address of handler's data block.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- ' Get double-click data.
- ClickS% = GetWord(S%, O% + ClickSOff) ' Peek at click speed.
- ClickW% = GetWord(S%, O% + ClickWOff) ' Peek at click width.
- ClickH% = GetWord(S%, O% + ClickHOff) ' Peek at click height.
-
- END SUB
-
- '============================================================================
- ' Returns the current event mask (mouse events currently being captured).
- '
- ' ' Determine which events are currently being trapped.
- ' IF OldMask% AND MouseMoved THEN ' Decimal: 1
- ' ' We are trapping mouse movement.
- ' ELSEIF OldMask% AND LButtonDown THEN ' Decimal: 2
- ' ' We are trapping left button presses.
- ' ELSEIF OldMask% AND LButtonUp THEN ' Decimal: 4
- ' ' We are trapping left button releases.
- ' .
- ' . \_ Other tests.
- ' . /
- '
- ' END IF
- '
- '============================================================================
- SUB GetEventMask (OldMask%)
-
- ' Get address of handler's data block.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- ' Get event mask flags.
- OldMask% = GetWord(S%, O% + EventMaskOff)
-
- END SUB
-
- '============================================================================
- ' Returns the number of events pending in the mouse event buffer.
- '============================================================================
- FUNCTION GetEventsPending
-
- T% = GetTailPtr ' Get tail position.
- H% = GetHeadPtr ' Get head position.
-
- N% = T% - H% ' Subtract head from tail
-
- BufferLen% = 90 ' Length of mouse event buffer.
- RecordLen% = 10 ' Length of each mouse event.
-
- IF N% < 0 THEN ' If the head pointer is
- N% = N% + BufferLen% ' greater than the tail,
- END IF ' wrap around.
-
- N% = N% \ RecordLen% ' Divide by the length of one event
- ' to get the actual value.
- GetEventsPending = N%
-
- END FUNCTION
-
- '============================================================================
- ' Returns the head pointer's position in the event buffer.
- '============================================================================
- FUNCTION GetHeadPtr
-
- ' Get address of handler's data block.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- H% = GetWord(S%, O% + HeadPtrOff) ' Get the value.
-
- ' Convert head pointer position relative to the first byte in the buffer.
- ' If you were to write a block of data to the buffer, S%:H% holds the actual
- ' head pointer's position. We must also subtract the distance from the
- ' beginning of the handler's data block to the first byte of the buffer.
-
- GetHeadPtr = H% - O% - BufferOff ' Return value.
-
- END FUNCTION
-
- '============================================================================
- ' Returns the tail pointer's position in the event buffer.
- '============================================================================
- FUNCTION GetTailPtr
-
- ' Get address of handler's data block.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- T% = GetWord(S%, O% + TailPtrOff) ' Get the value.
-
- ' Convert tail pointer position relative to the first byte in the buffer.
- ' If you were to write a block of data to the buffer, S%:H% holds the actual
- ' tail pointer's position. We must also subtract the distance from the
- ' beginning of the handler's data block to the first byte of the buffer.
-
- GetTailPtr = T% - O% - BufferOff ' Return value.
-
- END FUNCTION
-
- '============================================================================
- ' Restore handler's state
- '
- ' You must use InMouseSave() to save the handler's state first.
- '
- ' Buffer$: Holds handler's state (data block).
- '
- ' NOTE, the mouse event handler state is restored, not mouse driver state.
- '============================================================================
- '
- SUB InMouseRestore (Buffer$)
-
- ' Make sure buffer is the correct length.
- IF LEN(Buffer$) <> 132 THEN EXIT SUB
-
- ' Get status of handler.
- OldStatus% = InMouseState
-
- ' Disable before restoring state.
- CALL InMouseHandler(EventDisable)
-
- ' Point to handler's data area.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- ' Load fixed string with state.
- SaveState.Buffer = Buffer$
-
- ' Buffer pointer.
- BufSeg% = VARSEG(SaveState.Buffer)
- BufOff% = VARPTR(SaveState.Buffer)
-
- ' Restore handler's complete data block (132 bytes).
- FOR Address% = 0 TO 132 - 2 STEP 2
-
- ' Get data from buffer.
- Value% = GetWord(BufSeg%, BufOff% + Address%)
-
- ' Place data back in handler's data block.
- CALL PutWord(S%, O% + Address%, Value%)
-
- NEXT Address%
-
- ' If handler was active upon entry.
- IF OldStatus% AND EventEnable THEN
- CALL InMouseHandler(EventEnable)
- END IF
-
- END SUB
-
- '============================================================================
- ' Save handler's state, store in Buffer$.
- '
- ' NOTE, the mouse event handler state is saved, not the mouse driver state.
- '============================================================================
- SUB InMouseSave (Buffer$)
-
- ' Get status of handler.
- OldStatus% = InMouseState
-
- ' Disable before saving state.
- CALL InMouseHandler(EventDisable)
-
- ' Point to handler's data area.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- ' Buffer pointer.
- BufSeg% = VARSEG(SaveState.Buffer)
- BufOff% = VARPTR(SaveState.Buffer)
-
- ' Save handler's complete data block (132 bytes).
- FOR Address% = 0 TO 132 - 2 STEP 2
-
- ' Get data.
- Value% = GetWord(S%, O% + Address%)
-
- ' Store data in buffer.
- CALL PutWord(BufSeg%, BufOff% + Address%, Value%)
-
- NEXT Address%
-
- ' Return state to caller.
- Buffer$ = SaveState.Buffer
-
- ' If handler was active upon entry.
- IF OldStatus% AND EventEnable THEN
- CALL InMouseHandler(EventEnable)
- END IF
-
- END SUB
-
- '============================================================================
- ' Return the mouse event handler's status.
- '
- ' Status% = InMouseState
- '
- ' ' Determine status.
- ' IF Status% = 0 THEN
- ' Status$ = "Not Installed"
- ' ELSEIF Status% AND EventEnable THEN ' Decimal: 2
- ' Status$ = "Enabled"
- ' ELSEIF Status% AND EventDisable THEN ' Decimal: 4
- ' Status$ = "Disabled"
- ' END IF
- '
- '============================================================================
- FUNCTION InMouseState
-
- ' Get address of handler's data block.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- ' Get the current status of event handler.
- InMouseState = GetWord(S%, O% + InMouseStateOff)
-
- END FUNCTION
-
- '============================================================================
- ' Set double-click settings.
- '
- ' ClickS% - Time frame in which a double-click will be registered.
- '
- ' ClickW% - Specifies the width (in pixels, on either side) that the pointer
- ' can move between clicks when double-clicking.
- '
- ' ClickH% - Specifies the height (in pixels, above and below) that the
- ' pointer can move between clicks when double-clicking.
- '============================================================================
- SUB SetDblClkSettings (ClickS%, ClickW%, ClickH%)
-
- ' Get address of handler's data block.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- ' Change double-click settings.
- CALL PutWord(S%, O% + ClickSOff, ClickS%) ' Set double-click speed.
- CALL PutWord(S%, O% + ClickWOff, ClickW%) ' Set double-click width.
- CALL PutWord(S%, O% + ClickHOff, ClickH%) ' Set double-click height.
-
- END SUB
-
- '============================================================================
- ' Specify which mouse events the handler will capture.
- '
- ' By default, the event handler captures the following events:
- '
- ' 1. All button events (presses and releases).
- ' 2. Double-clicking for all buttons.
- ' 3. Shift-state events (cannot be disabled).
- '
- ' Use following table to build your own event trapping mask.
- '
- ' Event: Turn On: Turn Off:
- ' ═════════════════════ ════════ ═════════
- ' Mouse Movement 1 -2
- ' Left Button Press 2 -3
- ' Left Button Release 4 -5
- ' Right Button Press 8 -9
- ' Right Button Release 16 -17
- ' Center Button Press 32 -33
- ' Center Button Release 64 -65
- ' ──────────────────────────────────────────
- '
- ' To trap left button press and release:
- '
- ' NewMask% = LButtonDown OR LButtonUp: CALL SetEventMask (NewMask%)
- '
- ' To turn off an event currently being captured:
- '
- ' ' Mask out mouse movement.
- ' NewMask% = NewMask% AND -2: CALL SetEventMask (NewMask%)
- '
- ' ' Or use the NOT operator.
- ' NewMask% = NewMask% AND NOT 1: CALL SetEventMask (NewMask%)
- '
- ' NOTE: The default for double-clicking is on. To turn this feature off, set
- ' the double-click speed to zero. See: SUB SetDblClkSettings().
- '
- '============================================================================
- SUB SetEventMask (NewMask%)
-
- ' Get status of handler.
- OldStatus% = InMouseState
-
- ' Disable the handler first.
- CALL InMouseHandler(EventDisable)
-
- ' Get address of handler's data block.
- S% = InMouseAddress(O%) ' S% = Segment, O% = Offset.
-
- ' Change event mask flags.
- CALL PutWord(S%, O% + EventMaskOff, NewMask%)
-
- ' We must enable handler before the
- ' new event mask will take effect.
- ' If handler was active upon entry.
- IF OldStatus% AND EventEnable THEN
- CALL InMouseHandler(EventEnable)
- END IF
-
- END SUB
-
-