Trystian Posted May 16, 2009 Posted May 16, 2009 Hello all,I have a 3dConnexion SpaceNavigator for my WindowsXP SP3 system. It's installed as a HID compliant device (ID: HID\VID_046D&PID_C626).I'd like to write an AutoIt program that will read from this device (or possibly others) to programmatically control other things. Has someone written a function to talk to HID devices yet? I was thinking 'MSDN -> User Input/Raw Input' might be a good starting point, but I'm not good with translating C#/VB code to AutoIt.Any help would be greatly appreciated.Thanks,-Trystian
Authenticity Posted May 16, 2009 Posted May 16, 2009 (edited) expandcollapse popup#include <Array.au3> #include <Array.au3> #include "RawInput.au3" #include <WinAPI.au3> ; For _WinAPI_GetLastError() and _WinAPI_GetLastErrorMessage() functions. Dim $tRIDL, $pRIDL, $iRIDL Dim $tBuff, $pBuff, $tszBuff, $pszBuff Dim $iRet, $iNumDevices = 0, $iSize = 0 Dim $tagRIDL = '' Dim $aDevices[1][2] $tRIDL = DllStructCreate($tagRAWINPUTDEVICELIST) $iRIDL = DllStructGetSize($tRIDL) Dim $iRet = _GetRawInputDeviceList(0, $iNumDevices, $iRIDL) If Not @error And $iNumDevices > 0 Then ReDim $aDevices[$iNumDevices][2] For $i = 1 To $iNumDevices $tagRIDL &= StringRegExpReplace($tagRAWINPUTDEVICELIST, '(\w+);', '${1}' & $i & ';') Next $tBuff = DllStructCreate($tagRIDL) $pBuff = DllStructGetPtr($tBuff) $iRet = _GetRawInputDeviceList($pBuff, $iNumDevices, $iRIDL) For $i = 1 To $iNumDevices $aDevices[$i-1][0] = DllStructGetData($tBuff, 'hDevice' & $i) $aDevices[$i-1][1] = DllStructGetData($tBuff, 'dwType' & $i) Next _ArrayDisplay($aDevices) For $i = 0 To $iNumDevices-1 $iRet = _GetRawInputDeviceInfo($aDevices[$i][0], $RIDI_DEVICENAME, '', $iSize) If $iSize > 0 Then $tszBuff = DllStructCreate('wchar[' & $iSize & ']') $pszBuff = DllStructGetPtr($tszBuff) $iRet = _GetRawInputDeviceInfo($aDevices[$i][0], $RIDI_DEVICENAME, $pszBuff, $iSize) ConsoleWrite(DllStructGetData($tszBuff, 1) & @LF) EndIf Next $tszBuff = 0 $tBuff = 0 EndIfThere are still a few things to workout with the error codes and when a function should set @error macro at all but anyway I hope you get the idea and the structures things. When you see something like $tagRAWINPUT_* the asterisk means that there are three -same size- structure for each raw input device, because of the union thing in structures but it could be worse if it was a 50-100 lines or so for one giant commented structure section which might make it more confusing.Maybe you'll come up with something more handy because I have no use for this functions as I have only a mouse and a keyboard and SendInput would sufficient.Edit: Corrected the array built using StringRegExpReplace...Edit2: Corrected _RegisterRawInputDevices().Edit3: Corrected _GetRawInputDeviceInfo() function description when used with flag $RIDI_DEVICEINFO.Edit4: Corrected _GetRawInputData() returned error value to be meaningful. RawInput.au3 Edited May 24, 2009 by Authenticity
ken82m Posted May 17, 2009 Posted May 17, 2009 Is it possible to prevent certain keystrokes from getting through like I did using this keyboard hook. I'm trying to find a way to do this and determine the device sending the keystroke. Thanks, Kenny #include <WinAPI.au3> Global $sHexKeys, $sMouse, $sString, $hHookKeyboard, $pStub_KeyProc HotKeySet("{F3}", "ExitNow");0x72 $pStub_KeyProc = DllCallbackRegister("_KeyProc", "int", "int;ptr;ptr") $hHookKeyboard = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($pStub_KeyProc), _WinAPI_GetModuleHandle(0), 0) While 1 Sleep(10) WEnd Func ExitNow() Exit EndFunc Func OnAutoITExit() DllCallbackFree($pStub_KeyProc) _WinAPI_UnhookWindowsHookEx($hHookKeyboard) EndFunc Func _KeyProc($nCode, $wParam, $lParam) If $nCode < 0 Then Return _WinAPI_CallNextHookEx($hHookKeyboard, $nCode, $wParam, $lParam) Local $KBDLLHOOKSTRUCT = DllStructCreate("dword vkCode;dword scanCode;dword flags;dword time;ptr dwExtraInfo", $lParam) Local $vkCode = DllStructGetData($KBDLLHOOKSTRUCT, "vkCode") If $vkCode <> 0x72 Then Return 1 _WinAPI_CallNextHookEx($hHookKeyboard, $nCode, $wParam, $lParam) EndFunc "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
Authenticity Posted May 17, 2009 Posted May 17, 2009 Why? Do you have more than one keyboard on the same computer/system or what? It seems like it's possible to not receive a WM_KEY* messages from a specific keyboard device but it has nothing to do with the hook procedure.
ken82m Posted May 17, 2009 Posted May 17, 2009 I have a remote for media center and my regular keyboard. both send keyboard events and windows see's them as a keyboard. so if I disable codes on one device it disabled the other. I'm trying to get it setup so that my remote still works. "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
ken82m Posted May 17, 2009 Posted May 17, 2009 (edited) Actually to make things easier I don't really need to block anything. I can just set a key is hit on my actual keyboard I perform an event EXCEPT when it is F3 In this case the event will be locking the computer F3 will be a hotkey to enable the keyboard So I really just need an example to pickup the device ID and key using a dll callback or something Kenny Edited May 17, 2009 by ken82m "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
Authenticity Posted May 17, 2009 Posted May 17, 2009 Sorry for long delay, after a little of debugging I find the tiny miny problem that drove me crazy ;] because of the rush to get it to work I've passed one parameter to the _GetRawInputDevices() ByRef which should be then pass as uint* and got the same annoying error back which telling me Invalid Flags and this stuff.... Give me I few minutes I'll post the code to get $WM_INPUT from your desired device but because I have no other devices other than mouse and keyboard I have nothing to test it with so I need you to help me. ;] Again, sorry for the long wait.
ken82m Posted May 17, 2009 Posted May 17, 2009 sorry? hey I'm just happy to be getting the help You must be getting sick of me and my keyboard hooks lol This is actually something completely different. The one you helped me with the other day worked perfect. "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
Authenticity Posted May 17, 2009 Posted May 17, 2009 (edited) Here, tell me if you can see an output message when using your remote keyboard, I believe you will but who knows:expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseUpx=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <RawInput.au3> #include <WinAPI.au3> HotKeySet('{ESC}', '_EXIT') Global $tRID_KD, $pRID_KD, $iRID_KD Global $tRIH, $iRIH Global $iNumDevices Global $hGUI $hGUI = GUICreate('Test', 100, 100) GUIRegisterMsg($WM_INPUT, 'OnInput') $tRID_KD = DllStructCreate($tagRAWINPUTDEVICE) $pRID_KD = DllStructGetPtr($tRID_KD) $iRID_KD = DllStructGetSize($tRID_KD) $tRIH = DllStructCreate($tagRAWINPUTHEADER) $iRIH = DllStructGetSize($tRIH) $iNumDevices = 1 DllStructSetData($tRID_KD, 'usUsagePage', 0x01) DllStructSetData($tRID_KD, 'usUsage', 0x06) DllStructSetData($tRID_KD, 'dwFlags', BitOR($RIDEV_NOLEGACY, $RIDEV_INPUTSINK)) DllStructSetData($tRID_KD, 'hwndTarget', $hGUI) _RegisterRawInputDevices($pRID_KD, $iNumDevices, $iRID_KD) While 1 Sleep(20) WEnd GUIDelete() Func OnInput($hwnd, $iMsg, $iwParam, $ilParam) Local $tRI_KD, $pRI_KD, $iRI_KB Local $iSize $tRI_KD = DllStructCreate($tagRAWINPUT_KEYBOARD) $pRI_KD = DllStructGetPtr($tRI_KD) $iRI_KB = DllStructGetSize($tRI_KD) _GetRawInputData($ilParam, $RID_INPUT, $pRI_KD, $iRI_KB, $iRIH) If Not @error Then ConsoleWrite(DllStructGetData($tRI_KD, 'Message') & @LF) ConsoleWrite(DllStructGetData($tRI_KD, 'VKey') & @LF) EndIf $tRI_KD = 0 Return 'GUI_RUNDEFMSG' EndFunc Func _EXIT() GUIDelete() Exit EndFuncEdit: Also, can you run the previous script and post the output? Edited May 17, 2009 by Authenticity
ken82m Posted May 17, 2009 Posted May 17, 2009 (edited) Nothing, I tried adding a msgbox to the begin of OnInput and it never comes up. So it looks like that function is never getting called Kenny Edited May 17, 2009 by ken82m "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
ken82m Posted May 17, 2009 Posted May 17, 2009 Sorry just saw your edit here's the output: \\?\HID#SaitekHotKeys#2&150b6877&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} \\?\HID#HpqRemHidDevice&Col02#5&2f051232&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030} \\?\HID#HpqRemHidDevice&Col01#5&2f051232&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} \\?\Root#RDP_KBD#0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd} \\?\HID#SaitekKeyboard#2&1d46170d&0&0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd} \\?\HID#HpqRemHidDevice&Col03#5&2f051232&0&0002#{884b96c3-56ef-11d1-bc8c-00a0c91405dd} \\?\ACPI#PNP0303#4&ef0d0fe&0#{884b96c3-56ef-11d1-bc8c-00a0c91405dd} \\?\Root#RDP_MOU#0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd} \\?\HID#SaitekMouse#2&7fd572c&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd} \\?\ACPI#SYN0138#4&ef0d0fe&0#{378de44c-56ef-11d1-bc8c-00a0c91405dd} It should be one of the two "HpqRemHidDevice" but I'm not sure which one. Kenny "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
Authenticity Posted May 17, 2009 Posted May 17, 2009 (edited) Usually it is the first one. Can you explain what do you mean by nothing? The WM_INPUT is never called from both the connected and the remote keyboard?Edit: Sorry, I've corrected the RawInput.au3 library but didn't upload the corrected one. In a minute. ;] Uploaded. Edited May 17, 2009 by Authenticity
ken82m Posted May 17, 2009 Posted May 17, 2009 (edited) Yeah, but it's being called now with the new UDF you uploaded. Here are the results Output from right arrow on keyboard 256 39 257 39 Output from right arrow on remote 256 39 257 39 Edited May 17, 2009 by ken82m "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
ken82m Posted May 18, 2009 Posted May 18, 2009 So I guess 256 = key down , 257 = key up. So that will give me the key info I need. I tried changing " $iNumDevices = 1 " to another number. I figured that was how I specified the device to check? 1 is the only option that returns any output, and it returns both devices. hmm, Is there any other info that can be returned that might help? Thanks, Kenny "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
ken82m Posted May 18, 2009 Posted May 18, 2009 (edited) I found this on MSDN, it deals with HID remotes and RawInput.It has some sample code to download.http://msdn.microsoft.com/en-us/library/ms...tdevices_topic5EDIT: This part looked interestingrid[0].usUsagePage = 0xFFBC; // adds HID remote control rid[0].usUsage = 0x88; rid[0].dwFlags = RIDEV_INPUTSINK; rid[0].hwndTarget = this.Handle; rid[1].usUsagePage = 0x0C; // adds HID remote control rid[1].usUsage = 0x01; rid[0].dwFlags = RIDEV_INPUTSINK; rid[0].hwndTarget = this.Handle; rid[2].usUsagePage = 0x0C; // adds HID remote control rid[2].usUsage = 0x80; rid[0].dwFlags = RIDEV_INPUTSINK; rid[0].hwndTarget = this.Handle; Edited May 18, 2009 by ken82m "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
Authenticity Posted May 18, 2009 Posted May 18, 2009 Yes, the first example on the page enumerates all the raw input devices on your machine (which is enumerate-able) and return the device type and the device handle. See what is the handles using the _ArrayDisplay() and compare to which one $ilParam in $WM_INPUT message is belong. You can build the array to contain only those devices of type keyboard $RIM_TYPEKEYBOARD. Example: #include <Array.au3> #include <RawInput.au3> Dim $tRIDL, $iRIDL Dim $tBuff, $pBuff Dim $iNumDevices, $iSize Dim $tagRIDL Dim $aKBDevices[1] = [0] $tRIDL = DllStructCreate($tagRAWINPUTDEVICELIST) $iRIDL = DllStructGetSize($tRIDL) _GetRawInputDeviceList(0, $iNumDevices, $iRIDL) If Not @error And $iNumDevices > 0 Then $tagRIDL = '' For $i = 0 To $iNumDevices-1 $tagRIDL &= StringRegExpReplace($tagRAWINPUTDEVICELIST, '(\w+);', '${1}' & $i & ';') Next $tBuff = DllStructCreate($tagRIDL) $pBuff = DllStructGetPtr($tBuff) _GetRawInputDeviceList($pBuff, $iNumDevices, $iRIDL) If Not @error Then For $i = 0 To $iNumDevices-1 If DllStructGetData($tBuff, 'dwType' & $i) = $RIM_TYPEKEYBOARD Then $aKBDevices[0] += 1 ReDim $aKBDevices[$aKBDevices[0]+1] $aKBDevices[$aKBDevices[0]] = DllStructGetData($tBuff, 'hDevice' & $i) EndIf Next EndIf _ArrayDisplay($aKBDevices) EndIf Then compare them to the $ilParam, I might be wrong so in case $ilParam is just a handle to $tagRAWINPUT_* then you can check the handle of the $tagRAWINPUTHEADER of the $tagRAWINPUT_KEYBOARD structure in $WM_INPUT handler. A little bit of reading. ;]
ken82m Posted May 18, 2009 Posted May 18, 2009 Well i tried but I give up, too many inputs I guess lol This is my output in the array of devices. [0]|4 [1]|0x00010045 [2]|0x00010043 [3]|0x00010041 [4]|0x000B003F I've been playing around with trying to read that info from $lparam with no success. I've does a good job getting some 0's lol Can i have a hint lol "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
Authenticity Posted May 18, 2009 Posted May 18, 2009 (edited) Read the last complete code with the $WM_INPUT handler and extract the handle of the device sending the input using:Func OnInput($hwnd, $iMsg, $iwParam, $ilParam) Local $tRI_KD, $pRI_KD, $iRI_KB Local $iSize $tRI_KD = DllStructCreate($tagRAWINPUT_KEYBOARD) $pRI_KD = DllStructGetPtr($tRI_KD) $iRI_KB = DllStructGetSize($tRI_KD) _GetRawInputData($ilParam, $RID_INPUT, $pRI_KD, $iRI_KB, $iRIH) If Not @error Then ConsoleWrite(DllStructGetData($tRI_KD, 'Message') & @LF) ConsoleWrite(DllStructGetData($tRI_KD, 'VKey') & @LF) ConsoleWrite(DllStructGetData($tRI_KD, 'hDevice') & @LF) EndIf $tRI_KD = 0 Return 'GUI_RUNDEFMSG' EndFunc$tagRAWINPUTHEADER is a member struct of the $tagRAWINPUT_* structs. See which handle match to the keyboard and which to the remote and compare them using the array. You can then ignore the remote and process only the keyboard inputs.Edit: Here, if you still don't have or whatever: ;]_DefRawInputProc ("$paRawInput, $iInputs, $iSizeHeader[, $hDll = 'user32.dll']") Calls the default raw input procedure to provide default processing for any raw input messages that an (required: #include <RawInput.au3>) _GetRawInputBuffer ("$pData, ByRef $iSize, $iSizeHeader[, $hDll = 'user32.dll']") Does a buffered read of the raw input data. (required: #include <RawInput.au3>) _GetRawInputData ("$hRawInput, $iCommand, $pData, ByRef $iSize, $iSizeHeader[, $hDll = 'user32.dll']") Gets the raw input from the specified device. (required: #include <RawInput.au3>) _GetRawInputDeviceInfo ("$hDevice, $iCommand, $pData, ByRef $iSize[, $hDll = 'user32.dll']") Gets information about the raw input device. (required: #include <RawInput.au3>) _GetRawInputDeviceList ("$pRawInputDeviceList, ByRef $iNumDevices, $iSize[, $hDll = 'user32.dll']") Enumerates the raw input devices attached to the system. (required: #include <RawInput.au3>) _GetRegisteredRawInputDevices ("$pRawInputDevices, ByRef $iNumDevices, $iSize[, $hDll = 'user32.dll']") Gets the information about the raw input devices for the current application. (required: #include <RawInput.au3>) _RegisterRawInputDevices ("$pRawInputDevices, ByRef $iNumDevices, $iSize[, $hDll = 'user32.dll']") Registers the devices that supply the raw input data. (required: #include <RawInput.au3>).. add to au3.user.calltips.api Edited May 18, 2009 by Authenticity
ken82m Posted May 18, 2009 Posted May 18, 2009 Yeah as soon as I got to this in your post my it kicked my brain over. ConsoleWrite(DllStructGetData($tRI_KD, 'hDevice') & @LF) I finally understand how these tags now. I had always scratched 'em up to one of those mysteries lol Reading all the comments in that UDF don't give me a headache anymore lol Thanks alot for all the time you put in on this! "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
ken82m Posted May 18, 2009 Posted May 18, 2009 I guess it's a lost cause, I outputted everything I could find.So much for that one I guess.And to think Microsoft built this damn remote.Source-ConsoleWrite(DllStructGetData($tRI_KD, 'Message') & @CR)ConsoleWrite(DllStructGetData($tRI_KD, 'VKey') & @CR)ConsoleWrite(DllStructGetData($tRI_KD, 'hDevice') & @CR)ConsoleWrite(DllStructGetData($tRI_KD, 'dwType') & @CR)ConsoleWrite(DllStructGetData($tRI_KD, 'MakeCode') & @CR)ConsoleWrite(DllStructGetData($tRI_KD, 'Flags') & @CR)ConsoleWrite(DllStructGetData($tRI_KD, 'Reserved') & @CR)ConsoleWrite(DllStructGetData($tRI_KD, 'ExtraInformation') & @CR & @CR)Keyboard256390x000B003F177200257390x000B003F177300Remote256390x000B003F177200257390x000B003F177300 "I believe that when we leave a place, part of it goes with us and part of us remains... Go anywhere, when it is quiet, and just listen.. After a while, you will hear the echoes of all our conversations, every thought and word we've exchanged.... Long after we are gone our voices will linger in these walls for as long as this place remains."
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now