Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

AHKHID - An AHK implementation of the HID functions


  • Please log in to reply
456 replies to this topic
TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007
Download
Last updated: August 22nd, 2010
 
Examples on how to use it:
  • Example 1 allows you to look at all the HID devices currently connected to your computer.
  • Example 2 allows you to register devices and examine the data coming out.
  • Example 3 is an example on how to detect mouse events, such as left mouse button up, wheel down, etc...
Documentation (also included in AHKHID.ahk)

How do I stop the default keypresses coming out of my device?
This is a question that has been asked often enough to warrant answering it on the main post. AHKHID cannot stop a device's default keypresses from generating. This functionality is not part of the raw input device interface that AHKHID wraps.

If you need to disable those default keypresses, you have three options, depending on which category you fit in:
  • If the device shows up as a remote, you can easily disable/modify the keys sent by modying the registry. For more information on this technique, see Step 5 of the tutorial posted below (second post in this thread).
  • If it does not show up as a remote, but does show up in the Other tab whose TLC when registered allows you to capture all the keys, then you can try uninstalling the keyboard. For more information on this technique, see here.
  • If it does not show up as a remote or as a device in the Other tab, but as a keyboard only, then you can try registering the keyboard TLC (UsPg 1 and Us 6) and filter the relevant keypresses. Look here for a sample script on how to do that. Don't look at the second method described in that post, it does not work.If you somehow don't fit in any of these categories, then make a post and I'll see if there might be another way.
Extreme method: Disabling all simulated keypress events
This is another method which will disable all simulated keypresses (from devices, as well as from the Send command), but allow the physical keypresses to go through. It obviously has a huge drawback, but it's there if you really need it.
 
/*
This approach allows you to let through physical b presses while denying simulated presses. You can obviously
change it to whichever key you wish to filter. It requires a bit of explanation. We can't use the keyboard
hook, because otherwise simulated presses will not be caught. But we need to retrieve the physical state of
the buttons, which can't be done with GetKeyState() if the keyboard hook is not installed. This is why we have
to use the API directly. To not catch the simulated keypress sent here, we have to turn off the hotkey itself
before.

The problem with this method is that it will block ALL simulated b presses, not only the ones coming from
remotes.

The virtual-key code for b is 0x42. The VK code for other keys can be found at:
http://msdn.microsoft.com/en-us/library/ms645540.aspx

To test: physically pressing b will produce b, but pressing a, which sends a simulated b, will be blocked.
*/

b::
If (DllCall("GetAsyncKeyState", "int", 0x42, "ushort") >> 15) {
Hotkey, b,, Off
SendInput, b
Hotkey, b,, On
}
Return

a::SendInput, b

Acknowledgements:Thank you all for the help!
 
As always, comments and suggestions are welcome. As well as trouble with registering that one button on your keyboard. grin.png
Enjoy!


Changelog

August 22nd, 2010

- Added support for AHK_L x64

June 14th, 2010

- Fixed the auto-execute section getting executed twice if AHKHID is already included and AHKHID_UseConstants() is called.
- Added RIDEV_DEVNOTIFY (Vista and up only)

June 8th, 2010

- Added AHKHID_UseConstants() so that constants can be declared wihout having to include AHKHID (thanks coleprime)

March 5th, 2010

- Updated the naming convention to allow for integration in library
- Hardcoded the constants into the functions
- Added clear on double-click in Example 2
- Added copy device name on double-click in Example 1

April 29th, 2009

- Updated functions so that they use ErrorLevel instead of a MsgBox upon error.
- Clarified documentation so that return values are clearer to understand.

April 8th, 2009

- Removed functions' dependance on constants. This means that you don't have to put the #Include line in the auto-execute section anymore if you don't want to initialize the constants.

Edited by Lexikos, 22 August 2015 - 01:09 AM.
Removed images which had reverted to ads


TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007
Tutorial

Here is a real life example of how to use AHKHID.
When I bought my HP Media Center a few years ago, I also received this nice remote with a receiver which connects through USB. The remote is meant to be used with the Media Center interface.

(image lost)

However, I eventually changed computer but still had the remote. So, I started wondering if I could find a way to detect all the button presses and assign labels to each of them. Although some of them triggered keyboard events (like the arrow buttons, the numbers, the OK button and the volume up/down button), I had no way of knowing if it came from the remote or from the keyboard.

So, these are the steps I used (and the steps you can use for any other HID device).

1. Figuring out the device specs

First thing I had to figure out was to get the Vendor ID, Product ID, Version Number, and most importantly, the Usage Page and Usage the remote operates on. To do this, I fired up Example 1 and looked at the "Other" tab. The following picture is a screenshot of what I saw. In red are the "devices" registered to the remote (I know this because they only appeared after I plugged in the receiver).


(image lost)

As you can see, the three devices are from the remote. However, they all operate on a different Usage Page and/or Usage. Anyways, at least now I know what the Vendor ID, the Product ID and the Version Number are (which will be needed later on in the script in order to make sure the input comes from the remote).

2. Reverse engineering the data

So now that I know on which Usage Page/Usage the remote operates on, I can fire up Example 2 and look at the data coming out of it. However, since the remote possesses three different TLCs (TLC means the Usage Page and Usage values), I had to register the three of them. Also, I modified Example 2 so that the output also shows the Usage Page/Usage values from which the data came from (so that I can distinguish between the three). Then, I clicked the Call button and started pressing buttons.

(image lost)

This is the part where I had to "reverse engineer" the data. I realized that
[*:hov57uc3] The TLC with UsPg 65468 and Us 136 showed down and up events only for some buttons.
[*:hov57uc3] Similarly, the TLC with UsPg 12 and Us 1 showed down and up events only for some (other) buttons.
[*:hov57uc3] Together, those two TLCs did not cover all the buttons.
[*:hov57uc3] And most importantly, the TLC with UsPg 65468 and Us 137 showed an event for every button pressed, but only on the down event.3. Collecting data

I decided to therefore concentrate on the last TLC (the one with UsPg 65468 and Us 137) because it was the only one with access to all buttons and because I didn't really need the Up event. However, I obviously could have decided to support as many buttons with up/down events, but I just felt it would have been extra work for not much (for what I wanted to do with it).

So now, I had to make a list of the data received for each button press. I therefore created a nice spreadsheet where I typed out the name of all the buttons. I then modified Example 2 so that instead of adding data to the listbox, it would simply do SendInput % Bin2Hex(&uData, r) "{Enter}"
which means it would insert the data (in hex format) in the cell and then press Enter to go to the next cell. This is what I got:

(image lost)

As you can see, I noticed that the only thing that changed for each press was the value of the 6th byte (the 7th byte is also different, but it only alternates between 04 and 84, no matter the buttons pressed).

4. Creating a script

All I had left do to was to create a simple script which would register the remote and check the 6th byte on input to see which button was pressed. The goal of the script was to add remote functionality to VLC and MPC (Media Player Classic). Instead of creating a label for each button, I decided to create labels only when needed, such that the OnMessage function only had to check if the label existed before calling it. I also added a prefix to the label, such that the label to be called would depend on the program currently in focus. For example, if VLC is in focus, the prefix would be "VLC" such that when you press the button with value 22 (which is Play), the OnMessage function will call the label called VLC_22 (if it exists). This is the resulting script:

/*!

DVD Menu 36
Power 12
TV 70
Radio 80
Music 71
Pictures 73
Videos 74
Record 23
Rewind 21
Replay/Previous Track 27
Play 22
Pause 24
Stop 25
Forward 20
Skip/Next Track 26
Back 35
More/Information 15
Up Arrow 30
Left Arrow 32
Right Arrow 33
Down Arrow 31
OK 34
Volume Up 16
Volume Down 17
Windows Media Center 13
Mute 14
Channel/Page Up 18
Channel/Page Down 19
Live TV 37
Guide 38
Recorded TV 72
1 1
2/ABC 2
3/DEF 3
4/GHI 4
5/JKL 5
6/MNO 6
7/PQRS 7
8/TUV 8
9/WXYZ 9
* 29
0 0
# 28
Clear 10
Print 78
Enter 11

*/

;Must be in auto-execute section if I want to use the constants
#Include %A_ScriptDir%\AHKHID.ahk

;Create GUI to receive messages
Gui, +LastFound
hGui := WinExist()

;Intercept WM_INPUT messages
WM_INPUT := 0xFF
OnMessage(WM_INPUT, "InputMsg")

;Register Remote Control with RIDEV_INPUTSINK (so that data is received even in the background)
r := AHKHID_Register(65468, 137, hGui, RIDEV_INPUTSINK)

;Prefix loop
Loop {
Sleep 1000
If WinActive("ahk_class QWidget") Or WinActive("ahk_class VLC DirectX")
sPrefix := "VLC"
Else If WinActive("ahk_class Winamp v1.x") Or WinActive("ahk_class Winamp Video")
sPrefix := "Winamp"
Else If WinActive("ahk_class MediaPlayerClassicW")
sPrefix := "MPC"
Else sPrefix := "Default"
}

Return

InputMsg(wParam, lParam) {
Local devh, iKey, sLabel

Critical

;Get handle of device
devh := AHKHID_GetInputInfo(lParam, II_DEVHANDLE)

;Check for error
If (devh <> -1) ;Check that it is my HP remote
And (AHKHID_GetDevInfo(devh, DI_DEVTYPE, True) = RIM_TYPEHID)
And (AHKHID_GetDevInfo(devh, DI_HID_VENDORID, True) = 1118)
And (AHKHID_GetDevInfo(devh, DI_HID_PRODUCTID, True) = 109)
And (AHKHID_GetDevInfo(devh, DI_HID_VERSIONNUMBER, True) = 272) {

;Get data
iKey := AHKHID_GetInputData(lParam, uData)

;Check for error
If (iKey <> -1) {

;Get keycode (located at the 6th byte)
iKey := NumGet(uData, 5, "UChar")

;Call the appropriate sub if it exists
sLabel := sPrefix "_" iKey
If IsLabel(sLabel)
Gosub, %sLabel%
}
}
}

VLC_15: ;More
SendInput f ;Toggle fullscreen
Return

VLC_18: ;Channel Up
SendInput ^{Up}
Return

VLC_19: ;Channel Down
SendInput ^{Down}
Return

VLC_21: ;Rewind
SendInput !{Left}
Return

VLC_27: ;Previous Track
SendInput p
Return

VLC_22: ;Play
SendInput q
Return

VLC_24: ;Pause
SendInput {Space}
Return

VLC_25: ;Stop
SendInput s
Return

VLC_20: ;Forward
SendInput !{Right}
Return

VLC_26: ;Next Track
SendInput n
Return

MPC_15: ;More
SendInput !{Enter} ;Toggle fullscreen
Return

MPC_18: ;Channel Up
SendInput {Up}
Return

MPC_19: ;Channel Down
SendInput {Down}
Return

MPC_21: ;Rewind
SendInput !{Left}
Return

MPC_20: ;Forward
SendInput !{Right}
Return

MPC_27: ;Previous Track
SendInput !{End}
Return

MPC_26: ;Next Track
SendInput !{Home}
Return

MPC_22: ;Play
SendInput !p
Return

MPC_24: ;Pause
SendInput {Space}
Return

MPC_25: ;Stop
SendInput !s
Return
Extra: 5. Disabling/modifying original key functions

A lot of the buttons on my remote generated events when pressed. Some were keyboard events (e.g. the numbers 0 to 9 produced their respective numbers), and some were more advanced events (e.g. the power button would send the computer in standby). I wanted to disable these events so that they would not conflict with the new functions I've given the buttons. The user bidomo here showed us a way on exactly how to do that, and I will just run through that methods here. Note that you can also use this method to modify or create the default action of each key, without using AHKHID.

You first have to navigate in the registry to the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HidIr\Remotes\745a17a0-74d3-11d0-b6fe-00a0c90f57da. If your remote does not produce that key, then the following will not work. You might have other keys in that same Remotes key but as far as I understand, you cannot work with them. You can only work with the ones whose RemoteName value is RC6 based MCE remote.

Now, export that key (right-click the key, select Export, and save the file somewhere). The only value we'll modify is the ReportMappingTable value. Therefore, you can erase all the other sections contained in the file. Mine looks like this (after doing some formatting so that 7 digits were on each line):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HidIr\Remotes\745a17a0-74d3-11d0-b6fe-00a0c90f57da]
"ReportMappingTable"=hex:\
00,00,00,00,04,00,27,\
01,00,00,00,04,00,1e,\
02,00,00,00,04,00,1f,\
03,00,00,00,04,00,20,\
04,00,00,00,04,00,21,\
05,00,00,00,04,00,22,\
06,00,00,00,04,00,23,\
07,00,00,00,04,00,24,\
08,00,00,00,04,00,25,\
09,00,00,00,04,00,26,\
0a,00,00,00,04,00,29,\
0b,00,00,00,04,00,28,\
0c,00,00,00,03,82,00,\
0e,00,00,00,01,e2,00,\
0f,00,00,00,01,09,02,\
10,00,00,00,01,e9,00,\
11,00,00,00,01,ea,00,\
12,00,00,00,01,9c,00,\
13,00,00,00,01,9d,00,\
14,00,00,00,01,b3,00,\
15,00,00,00,01,b4,00,\
16,00,00,00,01,b0,00,\
17,00,00,00,01,b2,00,\
18,00,00,00,01,b1,00,\
19,00,00,00,01,b7,00,\
1a,00,00,00,01,b5,00,\
1b,00,00,00,01,b6,00,\
1c,00,00,00,04,02,20,\
1d,00,00,00,04,02,25,\
1e,00,00,00,04,00,52,\
1f,00,00,00,04,00,51,\
20,00,00,00,04,00,50,\
21,00,00,00,04,00,4f,\
22,00,00,00,04,00,28,\
23,00,00,00,01,24,02,\
26,00,00,00,01,8d,00,\
4e,00,00,00,01,08,02
I also sorted the lines, so that the first digit of each line went from smallest to largest. Before modifying any values, make a backup of this file (in case you want to restore the original key functions) and open the copy you wish to modify in a text editor. It might help you to do the same thing I did and separate the lines after every 7th digit.

Each line (or each consecutive 7 digits) represent a button and the default action associated with that button. To understand in details how it works, please read the PDF file to which bidomo linked in his post. The most important digit is the first one, as it tells you which key of the remote is associated with the following action (the following digits). For example, in the file I posted above, you can see that one of the lines is "0b,00,00,00,04,00,28". The digit 0b is the code representing the Enter button on my remote. How do I know this? There are two ways: you can either look at the PDF file, which will most likely tell you the correct value for each key on your remote, or, if you did Step 3, you can use the data there to know for sure which key on your remote is which line in the registry. For example, 0b in decimal is 11 which is, as reported in Step 3, the Enter key.

The advantage with the second method is that you will know exactly which button on your remote refers to which line in the registry. Also, the PDF file doesn't list all the keys. And most importantly, if your goal is to assign new events to each button, it's important for you to know that not all your remote buttons are described in ReportMappingTable. Therefore, using the keycode found in Step 3, you can create new lines for buttons which don't yet have a given function in the table. An example of this in my case are the DVD Menu and Live TV buttons, which have a keycode of 24, and 25 (in hex), which as you can see, are not in the original ReportMappingTable.

If your goal is to simply disable ALL the orignal events of your keys, you simply have to replace all the digits that follow keycodes by 00, like this:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\HidIr\Remotes\745a17a0-74d3-11d0-b6fe-00a0c90f57da]
"ReportMappingTable"=hex:\
00,00,00,00,00,00,00,\
01,00,00,00,00,00,00,\
02,00,00,00,00,00,00,\
03,00,00,00,00,00,00,\
04,00,00,00,00,00,00,\
05,00,00,00,00,00,00,\
06,00,00,00,00,00,00,\
07,00,00,00,00,00,00,\
08,00,00,00,00,00,00,\
09,00,00,00,00,00,00,\
0A,00,00,00,00,00,00,\
0B,00,00,00,00,00,00,\
0C,00,00,00,00,00,00,\
0D,00,00,00,00,00,00,\
0E,00,00,00,00,00,00,\
0F,00,00,00,00,00,00,\
10,00,00,00,00,00,00,\
11,00,00,00,00,00,00,\
12,00,00,00,00,00,00,\
13,00,00,00,00,00,00,\
14,00,00,00,00,00,00,\
15,00,00,00,00,00,00,\
16,00,00,00,00,00,00,\
17,00,00,00,00,00,00,\
18,00,00,00,00,00,00,\
19,00,00,00,00,00,00,\
1A,00,00,00,00,00,00,\
1B,00,00,00,00,00,00,\
1C,00,00,00,00,00,00,\
1D,00,00,00,00,00,00,\
1E,00,00,00,00,00,00,\
1F,00,00,00,00,00,00,\
20,00,00,00,00,00,00,\
21,00,00,00,00,00,00,\
22,00,00,00,00,00,00,\
23,00,00,00,00,00,00,\
24,00,00,00,00,00,00,\
25,00,00,00,00,00,00,\
26,00,00,00,00,00,00,\
46,00,00,00,00,00,00,\
47,00,00,00,00,00,00,\
48,00,00,00,00,00,00,\
49,00,00,00,00,00,00,\
4A,00,00,00,00,00,00,\
4E,00,00,00,00,00,00,\
50,00,00,00,00,00,00
And there you go. This is how to modify/disable the original function of your remote's buttons. This could, in theory, allow you to completely bypass the need for AHKHID by assigning key combinations to each remote button and catching those hotkeys in a regular AHK script.

Here's more reading material on the subject:

All About Media Center Remotes (advanced) - source of the informative PDF
Archive: Key Support, Keyboard Scan Codes, and Windows - information about HID Usage ID (needed to assign a certain keyboard event to a remote button)

Hope this helps!

danalec
  • Members
  • 225 posts
  • Last active: Oct 03 2014 05:31 PM
  • Joined: 20 Jul 2006
wow, awesome! this is a must have tool!
this really should be included in the official installation pack!!!

i loved the vlc/mpc stuff, great idea!

thanks for sharing it, wonderful work
when i get time, i'll test it with more different devices :D maybe i can ressurrect some old stuff here...

                                  [ profile ]


TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007
I'm glad you like it! :D
Definitely come back if you have any problems with your HID devices!

b0ring
  • Members
  • 2 posts
  • Last active: Apr 26 2009 12:23 PM
  • Joined: 23 Apr 2009
Firstly, a huge thanks for creating this especially since I'm running 64bit so AutoHotkeyRemoteControlDLL didn't work, and Girder hasn't seemed to work with HID since version 3.

I had to rejig your code a little to get it to work with my remote, it seems to be running fine but I'd like a little feedback on how I've set it up since I'm a complete newbie to autohotkey.

When running Example 2 to catch the data, mine is in the format "Data: 040002"; "Data: 040040"; etc. My code is as follows...

;Must be in auto-execute section if I want to use the constants
#Include %A_ScriptDir%\AHKHID.ahk

;Create GUI to receive messages
Gui, +LastFound
hGui := WinExist()

;Intercept WM_INPUT messages
WM_INPUT := 0xFF
OnMessage(WM_INPUT, "InputMsg")

;Register Remote Control with RIDEV_INPUTSINK (so that data is received even in the background)
r := HID_Register(65468, 136, hGui, RIDEV_INPUTSINK)
p := HID_Register(12, 1, hGui, RIDEV_INPUTSINK)

Return

InputMsg(wParam, lParam) {
    Local devh, iKey, sLabel
    
    Critical
    
    ;Get handle of device
    devh := HID_GetInputInfo(lParam, II_DEVHANDLE)
    
    ;Check that it is my HP remote
    If (HID_GetDevInfo(devh, DI_DEVTYPE, True) = RIM_TYPEHID)
        And (HID_GetDevInfo(devh, DI_HID_VENDORID, True) = 1894)
        And (HID_GetDevInfo(devh, DI_HID_PRODUCTID, True) = 516) 
	And (HID_GetDevInfo(devh, DI_HID_VERSIONNUMBER, True) = 1) {
        
        ;Get data
        HID_GetInputData(lParam, uData)	
	iKey := NumGet(uData, 0, "UInt")
	sLabel := "RC_" . iKey
	if IsLabel(sLabel)
		Gosub, %sLabel%
    }
}

;Home
RC_260:
Return

;Red
RC_32772:
	Run "C:\Program Files (x86)\CyberLink\PowerDVD\PowerDVD.exe"
Return

;Green
RC_2052:
Return

;Yellow
RC_4100:
Return

;Blue
RC_8196:
	Run "C:\Program Files (x86)\XBMC\XBMC.exe" -fs -p
Return

...

I played around on variations of the "NumGet(uData, 5, "UChar")" in your code but the only way I could find unique numbers was using "NumGet(uData, 0, "UInt")" but these differ largely from the data reported back in Example 2, such as the blue button having an 8196 code instead of the reported data of 042000. Do you know if this a reliable and safe way of capturing the buttons, since it seems to work perfectly?

TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007
OK, I have to go to work right. But I'll give you a more detailed response tonight.

All I can tell you for now, is to make a complete list of the data coming in for each button (like I did in Step 3). In my case, only one byte was different, the 6th one, hence the NumGet(uData, 5, "UChar"). It might be different in your case (if one byte is not enough to differentiate between buttons).

The example script I posted is really just an example. It's very device-specific in many ways. I'll try making a script "template" to help guide you.

n-l-i-d
  • Guests
  • Last active:
  • Joined: --
Very good stuff! 8)

TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007

I had to rejig your code a little to get it to work with my remote, it seems to be running fine but I'd like a little feedback on how I've set it up since I'm a complete newbie to autohotkey.

The script looks fine. However, I have a question. Do you actually need to register the TLC with Usage Page 65468 and Usage 136 ? Or is that just left-over from my script? Because the reason it's there in my script is because that's the TLC my remote uses. But unless yours does as well, you don't have to register it.

I played around on variations of the "NumGet(uData, 5, "UChar")" in your code but the only way I could find unique numbers was using "NumGet(uData, 0, "UInt")" but these differ largely from the data reported back in Example 2, such as the blue button having an 8196 code instead of the reported data of 042000. Do you know if this a reliable and safe way of capturing the buttons, since it seems to work perfectly?

Don't forget that the data coming out of Example 2 is in hexadecimal. When you use NumGet, you're using its decimal value. This might explain the discrepancy between the two reported data (8196 in hex is 2004 which is what Example 2 gave, except the bytes go from left to right instead of right to left, ie. the leftmost byte is the first byte). What you could do is to modify Example 2 so that it gives out the decimal

Very good stuff! 8)

Thanks!

b0ring
  • Members
  • 2 posts
  • Last active: Apr 26 2009 12:23 PM
  • Joined: 23 Apr 2009

Do you actually need to register the TLC with Usage Page 65468 and Usage 136 ? Or is that just left-over from my script?


The bulk of my remote buttons were on 65468 and 136 with a few extra ones on 12 and 1, so I did need both.

Don't forget that the data coming out of Example 2 is in hexadecimal. When you use NumGet, you're using its decimal value. This might explain the discrepancy between the two reported data (8196 in hex is 2004 which is what Example 2 gave, except the bytes go from left to right instead of right to left, ie. the leftmost byte is the first byte). What you could do is to modify Example 2 so that it gives out the decimal


Ah, okay. My main concern was just that I didn't know where these numbers were coming from or how they were represented, but if mine are using the same values but just in a different format that's fine by me. Just so long as it works and won't explode later on.

Thanks again for the script and this very efficient and helpful support. :D

LarryD
  • Guests
  • Last active:
  • Joined: --
First of all thank You for the great script!!!
I succesfully tested it on Windows 7 x64.

Is it possible somehow to repeat the generated keypresses (SendInput) if the user holds the remote button pressed for a longer time?

TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007

First of all thank You for the great script!!!
I succesfully tested it on Windows 7 x64.

That's great to hear, seeing as I only have XP to test with. :D

Is it possible somehow to repeat the generated keypresses (SendInput) if the user holds the remote button pressed for a longer time?

Yes, of course. As long as you have a way of knowing when the remote button is pressed down, and when it is pressed up (as you saw in the example I gave, for my script, I chose to discard the Up events).

There are multiple ways of doing it I'm sure, but one I can think of is to rig the Down event to a sub that starts a timer (which will repeat the SendInputs) and rig the Up event to a sub which disables the timer. Something like this (pseudocode - showing only the relevant parts):

InputMsg(wParam, lParam) {
    
    ;...
    
    ;Get the keycode
    iKey := NumGet(uData, 5, "UChar")
    
    If bDownEvent
        Gosub, KeyIsDown
    Else Gosub, KeyIsUp
}

KeyIsDown:
    SetTimer, MyTimer, 200 ;Set the interval here (ie. if you want faster repetitions while the key is down, you would put a smaller number)
    Gosub, MyTimer ;So that it starts the first keypress right away
Return

KeyIsUp:
    SetTimer, MyTimer, Off
Return

MyTimer:
    SendInput, The key is still down{!}
Return

Of course, you can easily modify the idea using the method I used to do this for multiple keys (by using dynamic labels). You'll also have to modify the algorithm if you want the keypresses to be sent every (say) 200 ms. only after the key has been down for (say) 500 ms. (to simulate the behaviour of keyboard key presses).

Let me know if you need more guidance. :)

LarryD
  • Guests
  • Last active:
  • Joined: --
Thank you for the quick replay!
Unfortunately I can detect just one event, the down event.
I'm trying to use an MCE remote (UsPg 65468 and Us 137).
Any ideas? Maybe reading multiple times with HID_GetInputData?

TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007
Unfortunately, there's no way around it. If you don't have an Up event, you can't know when the button is released, and therefore you can't know when to stop repeating the keypresses.

I find it surprising that your MCE remote doesn't send an Up event. Is it the same model as mine? Did you test the buttons under all registered TLCs? Don't forget also that the Up event is not necessarily on the same TLC as the Down event.

Micha
  • Members
  • 539 posts
  • Last active: Dec 31 2011 01:43 PM
  • Joined: 15 Nov 2005
Hi,
thanks for the script.
At my post (DLLCall: Support for Human Interface devices) I put a link to your solution.
I hope you'll continue developing it.
Ciao
Micha

TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007
Thank you Micha! I really appreciate the link. :D

I made little updates:

- Updated functions so that they use ErrorLevel instead of a MsgBox upon error.
- Clarified documentation so that return values are clearer to understand.