Jump to content
Bilgus

Given multiple Keyboards Determine Which was pressed

Recommended Posts

Bilgus
Posted (edited)

Recently a user asked given two keyboards how to determine which keyboard was pressed this is the start of such functionality

I was already given permission to post this example by a moderator before I bothered

;Bilgus 2018
;Determine which keyboard was pressed

#include <Array.au3>
#include <WinAPISys.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global Const $HWND_MESSAGE = (-3) ;create a message-only window when set as Parent

;RAWINPUTDEVICE Constants
Global Const $HID_USAGE_PAGE_GENERIC = 0x1
Global Const $HID_USAGE_GENERIC_KEYBOARD = 0x6

Global $ghSelectedDevice

Global $gaKeyboards = EnumRawKeyboards("\HID")
If IsArray($gaKeyboards) And $gaKeyboards[0][0] >= 1 Then $ghSelectedDevice = $gaKeyboards[1][0] ; hard coded change to suit

_ArrayDisplay($gaKeyboards, '_WinAPI_EnumRawInputDevices', "", 0, Default, "Handle|Type|VID|Keys") ;Not Needed...

Global $hTarget = GUICreate("main", 10, 10, Default, Default, Default, Default, $HWND_MESSAGE) ;Dummy window to recieve messages

Register_RawInput($HID_USAGE_PAGE_GENERIC, $HID_USAGE_GENERIC_KEYBOARD, $RIDEV_INPUTSINK, $hTarget) ;$RIDEV_INPUTSINK recieves input when not foreground

; Register WM_INPUT message
GUIRegisterMsg($WM_INPUT, 'WM_INPUT')

HotKeySet("{ESC}", _Exit)

While 1
    Sleep(1000)
WEnd

Func Device_Pressed()
    ConsoleWrite("Device Pressed" & @CRLF)
EndFunc   ;==>Device_Pressed

Func _Exit()
    Exit
EndFunc   ;==>_Exit

Func Register_RawInput($iUsagePage, $iUsage, $iFlags, $hTargetHwnd)
    Local $tRID = DllStructCreate($tagRAWINPUTDEVICE)
    DllStructSetData($tRID, 'UsagePage', $iUsagePage)
    DllStructSetData($tRID, 'Usage', $iUsage)
    DllStructSetData($tRID, 'Flags', $iFlags)
    DllStructSetData($tRID, 'hTarget', $hTargetHwnd)

    ; Register HID input to obtain info from devices
    _WinAPI_RegisterRawInputDevices($tRID)
EndFunc   ;==>Register_RawInput

Func WM_INPUT($hWnd, $iMsg, $wParam, $lParam) ;Callback from RawInput
    #forceref $iMsg, $wParam

    ;'struct;dword Type;dword Size;handle hDevice;wparam wParam;endstruct'
    Local $tRIH = DllStructCreate($tagRAWINPUTHEADER)

    If _WinAPI_GetRawInputData($lParam, $tRIH, DllStructGetSize($tRIH), $RID_HEADER) And DllStructGetData($tRIH, "Type") = $RIM_TYPEKEYBOARD Then
        ConsoleWrite("0x" & Hex(DllStructGetData($tRIH, "hDevice")) & @CRLF)
        If $ghSelectedDevice = DllStructGetData($tRIH, "hDevice") Then
            Device_Pressed()
        Else
            ;Different Device
            ConsoleWrite("Different Device Pressed" & @CRLF)
        EndIf
    EndIf

    Return $GUI_RUNDEFMSG ;Pass on to default winproc
EndFunc   ;==>WM_INPUT

Func EnumRawKeyboards($sDeviceNameMatch = "")
    ;Returns array of keyboard device IDs
    Local $tInfo, $aData = _WinAPI_EnumRawInputDevices()

    If IsArray($aData) Then
        Local $aKeyboards[$aData[0][0] + 1][4]

        ;'dword Size;dword Type;';'struct;dword KbType;dword KbSubType;dword KeyboardMode;dword NumberOfFunctionKeys;dword NumberOfIndicators;dword NumberOfKeysTotal;endstruc'
        Local $_tagRID_INFO_KEYBOARD = $tagRID_INFO_KEYBOARD

        If StringRight($_tagRID_INFO_KEYBOARD, 1) <> "t" Then $_tagRID_INFO_KEYBOARD &= "t" ; t is missing from endstruct

        Local $iCt = 0, $iSz
        Local $tInfo, $tDeviceName, $sDeviceName

        For $i = 1 To $aData[0][0]
            $tInfo = DllStructCreate($_tagRID_INFO_KEYBOARD)

            If _WinAPI_GetRawInputDeviceInfo($aData[$i][0], $tInfo, DllStructGetSize($tInfo), $RIDI_DEVICEINFO) And $aData[$i][1] = $RIM_TYPEKEYBOARD Then
                $iSz = _WinAPI_GetRawInputDeviceInfo($aData[$i][0], 0, 0, $RIDI_DEVICENAME) ;Get bytes needed
                $tDeviceName = DllStructCreate('wchar[' & $iSz + 1 & ']') ;Holds device name string

                If _WinAPI_GetRawInputDeviceInfo($aData[$i][0], $tDeviceName, DllStructGetSize($tDeviceName), $RIDI_DEVICENAME) Then
                    $sDeviceName = DllStructGetData($tDeviceName, 1)

                    If $sDeviceNameMatch <> "" And Not StringInStr($sDeviceName, $sDeviceNameMatch) Then ContinueLoop

                    $iCt += 1
                    $aKeyboards[$iCt][0] = $aData[$i][0] ;Handle
                    $aKeyboards[$iCt][1] = $aData[$i][1] ;Type
                    $aKeyboards[$iCt][2] = $sDeviceName
                    $aKeyboards[$iCt][3] = DllStructGetData($tInfo, "NumberOfKeysTotal")
                EndIf

            EndIf
        Next
        $aKeyboards[0][0] = $iCt ; Write count of keyboard devices to array
        ReDim $aKeyboards[$iCt + 1][4] ;Resize array
    EndIf
    Return $aKeyboards
EndFunc   ;==>EnumRawKeyboards

 

Edited by Bilgus
Cleaned Up Code Added Filter to Enum

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • alien4u
      By alien4u
      Hello.

      I'm trying to understand the RawInput UDF but I'm not very advanced with DllCalls and Struc.

      All the examples I found, which actually works with my bar scanner are using a GUI and Return 'GUI_RUNDEFMSG'.

      But I don't want to do that, what I want to do is be able to read the rawinput data from the USB barscanner without any GUI and base on what I read trigger some actions/functions.

      Anybody can provide a simple sample code?

      Thanks... 
    • MrCreatoR
      By MrCreatoR
       This UDF allows to set an events handler for Mouse device.
       
      The beginning...
      I searched for a way to disable the Mouse Primary click, and be able to call some function when the click event is received...
      Big thanks to amel27 for this one, i only organized the whole stuff to UDF style.
       
      Example:
      #include <GUIConstantsEx.au3> #include "MouseOnEvent.au3" HotKeySet("{ESC}", "_Quit") _Example_Intro() _Example_Limit_Window() Func _Example_Intro() MsgBox(64, "Attention!", "Let's set event function for mouse wheel *scrolling* up and down", 5) ;Set event function for mouse wheel *scrolling* up/down and primary button *down* action (call our function when the events recieved) _MouseSetOnEvent($MOUSE_WHEELSCROLLDOWN_EVENT, "_MouseWheel_Events") _MouseSetOnEvent($MOUSE_WHEELSCROLLUP_EVENT, "_MouseWheel_Events") _MouseSetOnEvent($MOUSE_PRIMARYDOWN_EVENT, "_MousePrimaryDown_Event") Sleep(3000) ;UnSet the events _MouseSetOnEvent($MOUSE_WHEELSCROLLDOWN_EVENT) _MouseSetOnEvent($MOUSE_WHEELSCROLLUP_EVENT) _MouseSetOnEvent($MOUSE_PRIMARYDOWN_EVENT) ToolTip("") MsgBox(64, "Attention!", "Now let's disable Secondary mouse button up action, and call our event function.", 5) _MouseSetOnEvent($MOUSE_SECONDARYUP_EVENT, "_MouseSecondaryUp_Event", 0, 1) Sleep(5000) _MouseSetOnEvent($MOUSE_SECONDARYUP_EVENT) ToolTip("") EndFunc Func _Example_Limit_Window() Local $hGUI = GUICreate("MouseOnEvent UDF Example - Restrict events on specific window") GUICtrlCreateLabel("Try to click on that specific GUI window", 40, 40, 300, 30) GUICtrlSetFont(-1, 12, 800) GUICtrlCreateLabel("Press <ESC> to exit", 10, 10) GUISetState() _MouseSetOnEvent($MOUSE_PRIMARYDOWN_EVENT, "_MousePrimaryDown_Event", $hGUI) ;A little(?) bugie when you mix different events :( ;_MouseSetOnEvent($MOUSE_SECONDARYUP_EVENT, "_MouseSecondaryUp_Event", $hGUI) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $GUI_EVENT_PRIMARYDOWN MsgBox(0, "", "Should not be shown ;)") EndSwitch WEnd _MouseSetOnEvent($MOUSE_PRIMARYDOWN_EVENT) ;_MouseSetOnEvent($MOUSE_SECONDARYUP_EVENT) EndFunc Func _MouseWheel_Events($iEvent) Switch $iEvent Case $MOUSE_WHEELSCROLLDOWN_EVENT ToolTip("Wheel Mouse Button (scrolling) DOWN Blocked") Case $MOUSE_WHEELSCROLLUP_EVENT ToolTip("Wheel Mouse Button (scrolling) UP Blocked") EndSwitch Return $MOE_BLOCKDEFPROC ;Block EndFunc Func _MousePrimaryDown_Event() ToolTip("Primary Mouse Button Down Blocked") Return $MOE_BLOCKDEFPROC ;Block EndFunc Func _MouseSecondaryUp_Event() ToolTip("Secondary Mouse Button Up Blocked") EndFunc Func _Quit() Exit EndFunc  
      Available Events Constants:
       
      ------------------------------------------
      CHANGELOG:
      Download:
      Attached:     MouseOnEvent.zip - v2.3
      Old version:
      MouseOnEvent_2.1.zip
      MouseOnEvent_2.0.zip
      MouseOnEvent_UDF_1.9.zip
      MouseSetOnEvent_UDF_1.8.zip
      MouseSetOnEvent_UDF_1.7.zip
      MouseSetOnEvent_UDF_1.6.zip
      MouseSetOnEvent_UDF_1.5.zip
      MouseSetOnEvent_UDF_1.4.zip
      MouseSetOnEvent_UDF_1.3.zip
      Previous downloads: 146 + 200 + 804
      MouseOnEvent.zip
      MouseOnEvent.zip
×