Jump to content

Given multiple Keyboards Determine Which was pressed


Bilgus
 Share

Recommended Posts

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
Link to comment
Share on other sites

  • 8 months later...
  • Moderators

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

 

Link to comment
Share on other sites

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
Link to comment
Share on other sites

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

Link to comment
Share on other sites

  • Moderators

@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.

"Profanity is the last vestige of the feeble mind. For the man who cannot express himself forcibly through intellect must do so through shock and awe" - Spencer W. Kimball

How to get your question answered on this forum!

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

  • 6 months later...

If i have two keyboards, how to block key from one, to remap key to do some script, or others operations.

The other keyboard must work as usual.

The script could be for example, open a program, connect to a database, execute select command, execute some key sequence.

With the code above, we can fin wich device and wich key is pressed but i didn't find how to block a device.

It's possible to find a key pressed and block some keys with a keyboard hook, but i didn't find how to determine the device.

If we use Wm_INPUT and keyboard hook, hook arrive before wm_input.

If wm_input arrive first, we could put a variable to block in the hook, but it's not.

Any help please. 

Edited by kaz
Link to comment
Share on other sites

i've search a lot after my last post, spend some time, sleep less and i finally found some code.

I did a small dll and it work pretty well.

i'll try to do without , only with autoit.

EDIT :

After some tests, i think it's not possible without using a dll

We must create a hook with $WH_KEYBOARD but it seem not working, only $WH_KEYBOARD_LL can be use with autoit.

If someone else can confirme.

EDIT 2 :

After plying a litle, it seem send function doesn't send raw information of any keyboard, so hDevice is empty.

 

Edited by kaz
Link to comment
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
 Share

×
×
  • Create New...