Jump to content
Bilgus

Given multiple Keyboards Determine Which was pressed

Recommended Posts

Bilgus

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
  • Like 2

Share this post


Link to post
Share on other sites
martinandersen3d
Posted (edited)

How do I get the key that is pressed? :-)

 

I would love to call a method like:

Funk keyboardAndCharacter($keyboardId. $keyPressedId)

Edited by martinandersen3d

Share this post


Link to post
Share on other sites
Melba23

martinandersen3d,

To do that would run into the forum prohibition on keyloggers as explained here:

So please do not pursue this any further.

M23


Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
Deye

Just a thought,

Now all is left is to think of a way of securing the keyboard to the users foreground window process with a blockinput applied on to other processes
Also that ALT cannot be sent without the user actually sending it from the keyboard device

Maybe some idea as described here can come into play

As in quick to post:   haven't tried anything yet .. 

Edit : just saw  BlockInputEx.au3  ..

Deye

Edited by Deye

Share this post


Link to post
Share on other sites
AXLE
On 1/9/2019 at 5:24 AM, Melba23 said:

martinandersen3d,

To do that would run into the forum prohibition on keyloggers as explained here:

So please do not pursue this any further.

M23

I just noticed this and just need to confirm the definition of "Keylogger" here. I have future plans for an app that allows Two users at one desktop, so Two keyboards and Two mice. It also incorporates the concept of an additional custom keyboard in a "Gaming" environment. This is not a new concept, but would something like that step over the boundaries here. I am guessing apps for testing scan-codes for damaged keys may be iffy as well?

AXLE


"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Share this post


Link to post
Share on other sites
JLogan3o13

@AXLE did you read the post to which Melba pointed you? It is pretty straight-forward; if you are checking for more than a handful of keys, it is not something we will support.


√-1 2^3 ∑ π, and it was delicious!

How to get your question answered on this forum!

Share this post


Link to post
Share on other sites
AXLE

JLogan3o13, Yes I read all. The fact that checking for keypress, keyboard scancodes, and user input from the keyboard in general is a necessary part of programming makes this a somewhat grey area. Trying to differentiate between what is 'Getting User keyboard Input' and a Keylogger is somewhat grey and easy to overstep under the definition of 'checking for a more than a few keys'. If this refers to 'Any or all keyboard Input', that's OK, I will be careful to not accidentally post code that may be viewed that way. If this is referring to Low Level capture from the windows message stream, then that's slightly different, but still requires some care on my behalf. So I am just asking to ensure that I don't accidentally post code that may be viewed that way :)

I you have or know of more information on this subject I will find that helpful.

AXLE


"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

Share this post


Link to post
Share on other sites
AXLE
43 minutes ago, AXLE said:

I you have or know of more information on this subject I will find that helpful.

The above question still applies. After searching for banned posts I am starting to gauge a little better.. Links to more examples of locked/banned will be helpful..

It's sad that AutoIt gets a bad rap for what is more easily achievable in other more mainstream languages.


"Writing code to carry out an intended set of tasks is relatively easy.
Writing code to carry out ONLY an intended set of tasks, well that can be a little more challenging."

Alex Maddern

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
×