Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Keyboard & Mouse Interface for PBCC

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Keyboard & Mouse Interface for PBCC

    The following code is a handy keyboard and mouse interface for PBCC.
    Please copy the following lines and paste it into a file 'kmiget.inc':

    Code:
    '===========================================================================
    '
    '   NAME
    '
    '     KMIGET - Keyboard & Mouse Interface: Get User Input
    '
    '   SYNOPSIS
    '
    '     #include "kmiget.inc"
    '
    '     wRetCode=kmiget(kmi_mode)
    '
    '     data passed:   kmi_mode  %KMI_NOWT = No Wait
    '                              %KMI_WAIT = Wait for Input
    '
    '     data returned: wRetCode  %KMI_NULL = No Input (No Wait mode only)
    '                              %KMI_DATA = Keyboard Data
    '                              %KMI_FUNC = Keyboard Function
    '                              %KMI_MMOV = Mouse Move
    '                              %KMI_MEVT = Mouse Button Event
    '                              %KMI_KBRK = Ctrl-Break Signal
    '
    '   DESCRIPTION
    '
    '     Actual data is returned in the global kmi structure:
    '
    '       Shift States: (Keyboard & Mouse Action)
    '           kmi.wShft  Shift Word:   1 = Right Alt
    '                                    2 = Left Alt
    '                                    4 = Right Ctrl
    '                                    8 = Left Ctrl
    '                                   16 = Shift
    '                                   32 = NumLock
    '                                   64 = Scroll Lock
    '                                  128 = Caps Lock
    '                                  256 = Enhanced Key
    '           kmi.bShft  Shift Byte:   1 = Shift, 2 = Ctrl 3 = Alt
    '
    '       Data/Function Keys
    '           kmi.bData  Data Byte
    '           kmi.bFunc  Function Byte
    '
    '       Mouse Position/Action
    '           kmi.wMouX  Horizontal Pouse Position
    '           kmi.wMouY  Vertical Mouse Position
    '           kmi.wMouE  Mouse event: %KMI_MMOVE = Mouse Movement
    '                                   %KMI_MLDCK = Mouse Left Doubleclick
    '                                   %KMI_MLBPR = Mouse Left Button Press
    '                                   %KMI_MLBRE = Mouse Left Button Release
    '                                   %KMI_MRDCK = Mouse Right Doubleclick
    '                                   %KMI_MRBPR = Mouse Right Button Press
    '                                   %KMI_MRBRE = Mouse Right Button Release
    '
    '
    '   DIAGNOSTICS
    '
    '     Alt-numeric-pad keys are returned as data bytes. Note, however,
    '     that kmiget behaves different depending on running Windows platform 1
    '     (Win95, Win98, WinME) or running platform 2 (WinNT, W2k, XP):
    '
    '     platform 1: 3 key strokes needed to compose a character. E.g. to
    '                 compose the character 'A' you need to type (Alt-hold)
    '                 '0', '6', '5' (Alt-release)
    '
    '     platform 2: only as many key strokes as needed. E.g. to compose
    '                 the character 'A' you to need to type (Alt-hold)
    '                 '6', '5' (Alt-release)
    '
    '     All composed characters are subject to modulo-256. If you type
    '     '8', '8', '8' kmiget will return "x" (decimal 120).
    '
    '
    '===========================================================================
    
    DECLARE FUNCTION  SetConsoleCtrlHandler LIB "KERNEL32.DLL" ALIAS _
                     "SetConsoleCtrlHandler" _
                     (BYVAL HandlerRoutine AS LONG, _
                      BYVAL nAdd AS LONG) AS LONG
    
    DECLARE FUNCTION GetAsyncKeyState LIB "USER32.DLL" ALIAS _
                     "GetAsyncKeyState" (BYVAL vKey AS LONG) AS INTEGER
    
    %VK_MENU  = &H12
    %VK_LMENU = &HA4
    %VK_RMENU = &HA5
    
    '---------------------------------------------------------------------------
    '
    '   Function Key Codes
    '   ------------------
    %KMI_BKSP    =   8
    %KMI_TAB     =   9
    %KMI_ESC     =  27
    %KMI_F1      =  59
    %KMI_F2      =  60
    %KMI_F3      =  61
    %KMI_F4      =  62
    %KMI_F5      =  63
    %KMI_F6      =  64
    %KMI_F7      =  65
    %KMI_F8      =  66
    %KMI_F9      =  67
    %KMI_F10     =  68
    %KMI_F11     = 133
    %KMI_F12     = 134
    %KMI_HOME    =  71
    %KMI_UP      =  72
    %KMI_PGUP    =  73
    %KMI_LEFT    =  75
    %KMI_RGHT    =  77
    %KMI_END     =  79
    %KMI_DOWN    =  80
    %KMI_PGDN    =  81
    %KMI_INS     =  82
    %KMI_DEL     =  83
    
    '
    '   Shift-Function
    '   --------------
    '
    %KMI_sBKSP   = 120
    %KMI_sTAB    =  15
    %KMI_sESC    = 121
    %KMI_sF1     =  84
    %KMI_sF2     =  85
    %KMI_sF3     =  86
    %KMI_sF4     =  87
    %KMI_sF5     =  88
    %KMI_sF6     =  89
    %KMI_sF7     =  90
    %KMI_sF8     =  91
    %KMI_sF9     =  92
    %KMI_sF10    =  93
    %KMI_sF11    = 135
    %KMI_sF12    = 136
    %KMI_sHOME   =  55
    %KMI_sUP     =  56
    %KMI_sPGUP   =  57
    %KMI_sLEFT   =  52
    %KMI_sRGHT   =  54
    %KMI_sEND    =  49
    %KMI_sDOWN   =  50
    %KMI_sPGDN   =  51
    %KMI_sINS    =  48
    %KMI_sDEL    =  46
    
    '
    '   Ctrl-Function
    '   -------------
    '
    %KMI_cBKSP   = 127
    %KMI_cTAB    = 148
    %KMI_cESC    = 170
    %KMI_cF1     =  94
    %KMI_cF2     =  95
    %KMI_cF3     =  96
    %KMI_cF4     =  97
    %KMI_cF5     =  98
    %KMI_cF6     =  99
    %KMI_cF7     = 100
    %KMI_cF8     = 101
    %KMI_cF9     = 102
    %KMI_cF10    = 103
    %KMI_cF11    = 137
    %KMI_cF12    = 138
    %KMI_cHOME   = 119
    %KMI_cUP     = 141
    %KMI_cPGUP   = 132
    %KMI_cLEFT   = 115
    %KMI_cRGHT   = 116
    %KMI_cEND    = 117
    %KMI_cDOWN   = 145
    %KMI_cPGDN   = 118
    %KMI_cINS    = 146
    %KMI_cDEL    = 147
    
    '
    '   Alt-Function
    '   ------------
    '
    %KMI_aBKSP   =  14
    %KMI_aA      =  30
    %KMI_aB      =  48
    %KMI_aC      =  46
    %KMI_aD      =  32
    %KMI_aE      =  18
    %KMI_aF      =  33
    %KMI_aG      =  34
    %KMI_aH      =  35
    %KMI_aI      =  23
    %KMI_aJ      =  36
    %KMI_aK      =  37
    %KMI_aL      =  38
    %KMI_aM      =  50
    %KMI_aN      =  49
    %KMI_aO      =  24
    %KMI_aP      =  25
    %KMI_aQ      =  16
    %KMI_aR      =  19
    %KMI_aS      =  31
    %KMI_aT      =  20
    %KMI_aU      =  22
    %KMI_aV      =  47
    %KMI_aW      =  17
    %KMI_aX      =  45
    %KMI_aY      =  21
    %KMI_aZ      =  44
    %KMI_aTAB    = 165
    %KMI_aESC    =   1
    %KMI_aF1     = 104
    %KMI_aF2     = 105
    %KMI_aF3     = 106
    %KMI_aF4     = 107
    %KMI_aF5     = 108
    %KMI_aF6     = 109
    %KMI_aF7     = 110
    %KMI_aF8     = 111
    %KMI_aF9     = 112
    %KMI_aF10    = 113
    %KMI_aF11    = 139
    %KMI_aF12    = 140
    %KMI_aHOME   = 151
    %KMI_aUP     = 152
    %KMI_aPGUP   = 153
    %KMI_aLEFT   = 155
    %KMI_aRGHT   = 157
    %KMI_aEND    = 159
    %KMI_aDOWN   = 160
    %KMI_aPGDN   = 161
    %KMI_aINS    = 162
    %KMI_aDEL    = 163
    
    '---------------------------------------------------------------------------
    
    '   Mode Codes
    '   ----------
    %KMI_NOWT    =   0
    %KMI_WAIT    =   1
    
    '---------------------------------------------------------------------------
    
    '   Result Codes
    '   ------------
    %KMI_NULL    =   0
    %KMI_DATA    =   1
    %KMI_FUNC    =   2
    %KMI_MMOV    = 129
    %KMI_MEVT    = 130
    %KMI_KBRK    = 255
    
    '---------------------------------------------------------------------------
    
    '   Mouse Event Codes
    '   -----------------
    %KMI_MMOVE   =   1    ' Mouse Movement
    %KMI_MLDCK   =   2    ' Mouse Left Doubleclick
    %KMI_MLBPR   =   4    ' Mouse Left Button Press
    %KMI_MLBRE   =   8    ' Mouse Left Button Release
    %KMI_MRDCK   =  16    ' Mouse Right Doubleclick
    %KMI_MRBPR   =  32    ' Mouse Right Button Press
    %KMI_MRBRE   =  64    ' Mouse Right Button Release
    
    '---------------------------------------------------------------------------
    '
    '   Global kmi vars
    '   ---------------
    '
    type kmiglob
         wShft as word
         bShft as byte
         bData as byte
         bFunc as byte
         wBkhd as word
         wFtim as word
         wMouX as word
         wMouY as word
         wMouE as word
    end type
    
    global kmi as kmiglob
    
    '---------------------------------------------------------------------------
    '
    '   Aux. kmi-Subs
    '   -------------
    '
    FUNCTION kmimevent(p3 as string) as byte
        dim p6 as byte
        dim p7 as byte
        dim p8 as byte
        p6=asc(p3,3)
        p7=asc(p3,4)
        if (p6 and 1)                then p8=p8 or %KMI_MMOVE
        if (p6 and 2) and (p7 and 1) then p8=p8 or %KMI_MLDCK
        if (p6 and 4) and (p7 and 1) then p8=p8 or %KMI_MLBPR
        if (p6 and 8) and (p7 and 1) then p8=p8 or %KMI_MLBRE
        if (p6 and 2) and (p7 and 2) then p8=p8 or %KMI_MRDCK
        if (p6 and 4) and (p7 and 2) then p8=p8 or %KMI_MRBPR
        if (p6 and 8) and (p7 and 2) then p8=p8 or %KMI_MRBRE
        function=p8
    end function
    
    function kmi_breakhandler() as long
        kmi.wBkhd=1
        kmi_breakhandler=1
    end function
    
    sub GetShiftState
        kmi.wShft = inshift
        kmi.bShft = 0
        if (kmi.wShft and 16) then kmi.bShft = 1
        if (kmi.wShft and 12) then kmi.bShft = 2
        if (kmi.wShft and  3) then kmi.bShft = 3
    end sub
    
    function ModFunc(byval bInput as byte, byval bShiftState as byte) as byte
        local bResult as byte
    modf0010:
        ! push eax
        ! push ebx
        ! push edx
        ! push esi
        ! xor edx,edx
        ! mov al,bInput
        ! mov dl,bShiftState
        ! xor esi,esi
    modf0110:
        ! cmp dword ptr modftab[esi],0
        ! je  modf0130
        ! cmp byte ptr modftab[esi],al
        ! je  modf0120
        ! add esi,5
        ! jmp modf0110
    modf0120:
        ! add esi,edx
        ! inc esi
        ! mov al,modftab[esi]
    modf0130:
        ! mov bResult,al
        ! pop esi
        ! pop edx
        ! pop ebx
        ! pop eax
        function=bResult
        exit function
    modftab:
        ! db 008, %KMI_BKSP, %KMI_sBKSP, %KMI_cBKSP, %KMI_aBKSP
        ! db 009, %KMI_TAB,  %KMI_sTAB,  %KMI_cTAB,  %KMI_aTAB
        ! db 015, %KMI_TAB,  %KMI_sTAB,  %KMI_cTAB,  %KMI_aTAB
        ! db 027, %KMI_ESC,  %KMI_sESC,  %KMI_cESC,  %KMI_aESC
        ! db 059, %KMI_F1,   %KMI_sF1,   %KMI_cF1,   %KMI_aF1
        ! db 060, %KMI_F2,   %KMI_sF2,   %KMI_cF2,   %KMI_aF2
        ! db 061, %KMI_F3,   %KMI_sF3,   %KMI_cF3,   %KMI_aF3
        ! db 062, %KMI_F4,   %KMI_sF4,   %KMI_cF4,   %KMI_aF4
        ! db 063, %KMI_F5,   %KMI_sF5,   %KMI_cF5,   %KMI_aF5
        ! db 064, %KMI_F6,   %KMI_sF6,   %KMI_cF6,   %KMI_aF6
        ! db 065, %KMI_F7,   %KMI_sF7,   %KMI_cF7,   %KMI_aF7
        ! db 066, %KMI_F8,   %KMI_sF8,   %KMI_cF8,   %KMI_aF8
        ! db 067, %KMI_F9,   %KMI_sF9,   %KMI_cF9,   %KMI_aF9
        ! db 068, %KMI_F10,  %KMI_sF10,  %KMI_cF10,  %KMI_aF10
        ! db 087, %KMI_F11,  %KMI_sF11,  %KMI_cF11,  %KMI_aF11
        ! db 088, %KMI_F12,  %KMI_sF12,  %KMI_cF12,  %KMI_aF12
        ! db 071, %KMI_HOME, %KMI_sHOME, %KMI_cHOME, %KMI_aHOME
        ! db 072, %KMI_UP,   %KMI_sUP,   %KMI_cUP,   %KMI_aUP
        ! db 073, %KMI_PGUP, %KMI_sPGUP, %KMI_cPGUP, %KMI_aPGUP
        ! db 075, %KMI_LEFT, %KMI_sLEFT, %KMI_cLEFT, %KMI_aLEFT
        ! db 077, %KMI_RGHT, %KMI_sRGHT, %KMI_cRGHT, %KMI_aRGHT
        ! db 079, %KMI_END,  %KMI_sEND,  %KMI_cEND,  %KMI_aEND
        ! db 080, %KMI_DOWN, %KMI_sDOWN, %KMI_cDOWN, %KMI_aDOWN
        ! db 081, %KMI_PGDN, %KMI_sPGDN, %KMI_cPGDN, %KMI_aPGDN
        ! db 082, %KMI_INS,  %KMI_sINS,  %KMI_cINS,  %KMI_aINS
        ! db 083, %KMI_DEL,  %KMI_sDEL,  %KMI_cDEL,  %KMI_aDEL
        ! db 127, %KMI_BKSP, %KMI_sBKSP, %KMI_cBKSP, %KMI_aBKSP
        ! db 240, %KMI_ESC,  %KMI_sESC,  %KMI_cESC,  %KMI_aESC
        ! db 000, %KMI_NULL, %KMI_NULL,  %KMI_NULL,  %KMI_NULL
    end function
    
    
    '---------------------------------------------------------------------------
    '
    '   KMIGET - Keyboard/Mouse Interface
    '   ---------------------------------
    '
    '   retcode=kmiget(kmi_mode)
    '           passed   : kmi_mode %KMI_NOWT no wait for input
    '                               %KMI_WAIT wait for input
    '
    '           returns  : function value
    '                      %KMI_NULL = none
    '                      %KMI_DATA = Data Byte       (in kmi_bData)
    '                      %KMI_FUNC = Function Key    (in kmi_bFunc)
    '                      %KMI_MMOV = Mouse Movement
    '                      %KMI_MEVT = Mouse Event
    '                      %KMI_KBRK = Keyboard Break  (kmi_bFunc=255)
    '
    function kmiget(kmi_mode as word) as word
        local  sInput  as string
        local  ilInpL  as long
        local  bNumVal as byte
        static ilSwMen as integer
        static bNumPad as byte
        static sNumPad as string
        static iRAsync as integer
        static iLAsync as integer
        if kmi.wFtim=0 then
           SetConsoleCtrlHandler codeptr(kmi_breakhandler),1
           mouse on
           mouse 3, double, move, down, up
           kmi.wFtim=1
           kmi.wBkhd=0
        end if
    
        while (-1)
    
           while (-1)
             iRAsync=getAsyncKeyState(%VK_MENU)
             if iRAsync<0 then iRAsync=-1
             if iRAsync>-1 then iRAsync=1
             if iRAsync<>iLAsync then
                if (iRAsync=1) and (iLAsync=-1) then
                   if len(sNumPad) then ilSwMen=1
                end if
                iLAsync=iRAsync
             end if
             if kmi.wBkhd then exit loop
             if instat then exit loop
             if kmi_mode=%KMI_NOWT then exit loop
             if ilSwMen then exit loop
             sleep 1
           wend
    
           sInput=inkey$
           ilInpL=len(sInput)
    
           select case ilInpL           ' Data Length Dispatcher
    
             case 0                     ' Break detect / No Wait
               if kmi.wBkhd then
                  kmiget=%KMI_KBRK
                  kmi.bFunc=%KMI_KBRK
                  kmi.bData = 0
                  kmi.wBkhd = 0
                  bNumPad   = 0
                  sNumPad   = ""
                  exit loop
               end if
    
               if ilSwMen then
                     kmi.bData=val(sNumPad) mod 256
                     kmi.bFunc=0
                     kmiget=%KMI_DATA
                     GetShiftState
                     bNumPad   = 0
                     sNumPad   = ""
                     ilSwMen   = 0
                     exit loop
               end if
    
               if kmi_mode=%KMI_NOWT then
                  kmiget=%KMI_NULL
                  exit loop
               end if
    
             case 1                     ' Data Byte
               GetShiftState
               kmi.bData=asc(sInput)
               select case kmi.bData
                 case 8, 9, 27, 127, 240
                   kmi.bFunc=ModFunc(kmi.bData,kmi.bShft)
                   kmiget=%KMI_FUNC
                 case else
                   kmiget=%KMI_DATA
                end select
                bNumPad   = 0
                sNumPad   = ""
                exit loop
    
             case 2                     ' Function Key
               GetShiftState
               kmi.bFunc=ModFunc(asc(sInput,2),kmi.bShft)
               bNumVal=instr(chr$(162,159,160,161,155,76,157,151,152,153), _
                  chr$(kmi.bFunc))
               if bNumVal>0 and (kmi.wShft and 256)=0 then
                  incr bNumPad
                  sNumPad=sNumPad+format$(bNumVal-1,"0")
                  if bNumPad=3 then
                     kmi.bData=val(sNumPad) mod 256
                     kmi.bFunc=0
                     kmiget=%KMI_DATA
                     bNumPad   = 0
                     sNumPad   = ""
                     exit loop
                  end if
                  exit select
               end if
               kmiget=%KMI_FUNC
               bNumPad = 0
               sNumPad = ""
               exit loop
    
             case 4                     ' Mouse Movement/Event
               GetShiftState
               select case asc(sInput,3) ' Mouse Move/Event Dispatcher
                 case 1     ' movement
                   if mousex=kmi.wMouX and mousey=kmi.wMouY then exit select
                   kmi.wMouX=mousex
                   kmi.wMouY=mousey
                   if asc(sInput,4)=1 then kmi.wMouE=%KMI_MMOVE
                   kmiget=%KMI_MMOV
                   exit loop
                 case 2     ' double click
                   kmiget=%KMI_MEVT
                   kmi.wMouX=mousex
                   kmi.wMouY=mousey
                   if asc(sInput,4)=1 then kmi.wMouE=%KMI_MLDCK
                   if asc(sInput,4)=2 then kmi.wMouE=%KMI_MRDCK
                   kmiget=%KMI_MEVT
                   exit loop
                 case 4     ' button press
                   kmiget=%KMI_MEVT
                   kmi.wMouX=mousex
                   kmi.wMouY=mousey
                   if asc(sInput,4)=1 then kmi.wMouE=%KMI_MLBPR
                   if asc(sInput,4)=2 then kmi.wMouE=%KMI_MRBPR
                   kmiget=%KMI_MEVT
                   exit loop
                 case 8     ' button release
                   kmiget=%KMI_MEVT
                   kmi.wMouX=mousex
                   kmi.wMouY=mousey
                   if asc(sInput,4)=1 then kmi.wMouE=%KMI_MLBRE
                   if asc(sInput,4)=2 then kmi.wMouE=%KMI_MRBRE
                   kmiget=%KMI_MEVT
                   exit loop
               end select
               if kmi_mode=%KMI_WAIT then exit select
               exit loop
           end select
        wend
    
    end function
    -----------------------------------

    And the following lines mey be used to test the features of kmiget:

    Code:
    #dim all
    #compile exe
    #include "kmiget.inc"
    
    function disevent(p5 as word) as string
        if p5=%KMI_MMOVE then disevent="Mouse move"
        if p5=%KMI_MLDCK then disevent="Mouse Left Doubleclick"
        if p5=%KMI_MLBPR then disevent="Mouse Left Button Press"
        if p5=%KMI_MLBRE then disevent="Mouse Left Button Release"
        if p5=%KMI_MRDCK then disevent="Mouse Right Doubleclick"
        if p5=%KMI_MRBPR then disevent="Mouse Right Button Press"
        if p5=%KMI_MRBRE then disevent="Mouse Right Button Release"
    end function
    
    function disshift() as string
        local p5 as string
        p5 = ""
        if (kmi.wShft and   1) then p5=p5+" Right Alt "
        if (kmi.wShft and   2) then p5=p5+" Left Alt "
        if (kmi.wShft and   4) then p5=p5+" Right Ctrl "
        if (kmi.wShft and   8) then p5=p5+" Left Ctrl "
        if (kmi.wShft and  16) then p5=p5+" Shift "
        if (kmi.wShft and  32) then p5=p5+" NumLock "
        if (kmi.wShft and  64) then p5=p5+" Scroll Lock "
        if (kmi.wShft and 128) then p5=p5+" Caps Lock "
        if (kmi.wShft and 256) then p5=p5+" Enhanced Key "
        disshift=p5
    end function
    
    function pbmain() as long
        dim rc as long
        stdout "Type <ESC> to exit"+$CR+$LF
        while (-1)
           rc=kmiget(%KMI_NOWT)
           select case rc
             case %KMI_DATA
               stdout "normal key:   "+str$(kmi.bData)+" "+chr$(kmi.bData)+disshift
             case %KMI_FUNC
               stdout "function key: "+str$(kmi.bFunc)+disshift
               if kmi.bFunc=27 then exit loop
             case %KMI_MMOV
               stdout "mouse move:   "+str$(kmi.wMouX)+str$(kmi.wMouY)+disshift
             case %KMI_MEVT
               stdout "mouse event:  "+str$(kmi.wMouX)+str$(kmi.wMouY)+" "+disevent(kmi.wMouE)+disshift
             case %KMI_KBRK
               stdout "Keyb Break:   "+str$(kmi.bFunc)
             case %KMI_NULL
               sleep 1
           end select
        wend
    
    end function
    ------------------------

    Enjoy!

    regards, Albert

    ------------------




    [This message has been edited by Albert Richheimer (edited October 09, 2002).]
    „Let the machine do the dirty work.“
    The Elements of Programming Style, Brian W. Kernighan, P. J. Plauger 1978
Working...
X