I'm prototyping input for an app that requires chorded input with non-standard modifiers -- literally hundreds of chords.
Because this experiment involves sometimes pressing two or three or four LETTER keys down simultaneously or near-simultaneously, my initial tests with the X & Y:: method of custom modifiers results in a lot of misfires during fast typing. It also creates a lot of key-state-checking overhead to find the second, third, etc. modifiers, since they are not the usual ones and there are literally hundreds of modifier possibilities (basically, any other keys). I think I'm going to have to literally record timestamps of key-up and key-down events and compare them with certain tolerances, key-down orders, etc. to determine whether a particular sequence is in fact a chord, or just rapid typing.
My proposed solution is to use an "anykey down or up global hotstring" (or the best approximation thereof), log the key down and key up event time in an object. On the side, I'd keep a collection of (a) currently-down keys and (b) recently-down-but-now-up keys mapped back to the object with timestamps -- and then do some quick comparisons to see whether the last key event was a chord or a letter. I'll then pass the name of the determined chord or letter to a keyed-object {unique_chord_string : function_object, ...} and let that determine what to do with the key event.
I know you all are busy, but I'm hoping someone could give me pointers on two topics:
1. Global AnyKey Hotkey. In my search of the forums, I've seen lots of requests for a way to do a global anykey hotkey. In many cases, it's because people want to manage something offline that could be managed better by AHK. In my case, because I have to check millisecond tolerances of both key-up and key-down events to determine the difference between fast typing and slightly non-simultaneous chording, I don't think I have a choice. Is there a global anykey hotkey, apart from stacking labels or looping a hotkey command to auto-create the labels? I've seen someone recommend using Input but I'm thinking that won't work because I have to log key UP and down events to compare timestamps, and I'd also prefer not to have anything looping/racing when the keyboard is otherwise idle. Any suggestions?
2. Raw Access to Key List. Is there any undocumented or raw programmatic access to the key list, which it appears AHK is already creating for itself? That might be better and more efficient than logging a bunch of ups/downs that have already been logged. I know you can see the last hotkey and the prior hotkey, but is there something with more history than that?
In case it helps, I'm writing this in v2, but any advice would be appreciated, either from v1 or v2 experts... Thanks!
Global "anykey" hotkey for raw processing Topic is solved
Re: Global "anykey" hotkey for raw processing
I'm not sure I get what your asking here, but if you're interested in something like hotkeys of type a & b & c &... I have made such a script (class actually) but it has not been very well tested, initial testing seemed fine though. If you want to try it out I'll be happy to send it to you. I did lose interest and motivation to finish it properly. Anyhow, I might not have access to my computer for a while, so if you are in a hurry you'll have to hope that someone else here helps you out. Cheers.
Re: Global "anykey" hotkey for raw processing
You talk about chording, and how that is different from normal typing. It may be helpful to explain what chording is and how that differs from normal typing for people to give you an idea.
You already seemed to have rejected my idea where you create all hotkeys. The first code block is below in case someone stumbles on this topic and likes that idea anyhow. If you come to accept it, I would suggest recording the time goes down (in a variable?) and then getting the time when the key is released after a KeyWait. The trouble is with threading though, as I'm not sure how pressing 4 hotkeys down and releasing them affects how the KeyWait is done. In other words, if I press ABCD all down but release in the order ABCD, because the D hotkey may have interrupted the C hotkey, which may have interrupted the B hotkey, which may have interrupted the A hotkey, AHK may not detect my release of the A, B, and C keys until my D key is released and the chain of interruption is undone. Hmm, it seems that keywait alone is not enough because of the issue I expected with threading (though I couldn't get a rhyme or reason to it in my testing; probably a poor testing method). But the second code block demonstrates a proof of concept for timing keystrokes.
You already seemed to have rejected my idea where you create all hotkeys. The first code block is below in case someone stumbles on this topic and likes that idea anyhow. If you come to accept it, I would suggest recording the time goes down (in a variable?) and then getting the time when the key is released after a KeyWait. The trouble is with threading though, as I'm not sure how pressing 4 hotkeys down and releasing them affects how the KeyWait is done. In other words, if I press ABCD all down but release in the order ABCD, because the D hotkey may have interrupted the C hotkey, which may have interrupted the B hotkey, which may have interrupted the A hotkey, AHK may not detect my release of the A, B, and C keys until my D key is released and the chain of interruption is undone. Hmm, it seems that keywait alone is not enough because of the issue I expected with threading (though I couldn't get a rhyme or reason to it in my testing; probably a poor testing method). But the second code block demonstrates a proof of concept for timing keystrokes.
Code: Select all
#Persistent
Loop, 255
Hotkey, % "~" Format("vk{:x}",A_Index), pressed, On
return
pressed:
Tooltip % "You pressed " GetKeyName(SubStr(A_ThisHotkey,2))
return
Code: Select all
a::
b::
c::
d::
time_down_%A_thishotkey%:=A_TickCount
KeyWAit, %A_ThisHotkey%
return
a up::
b up::
c up::
d up::
prefix:=SubStr(A_ThisHotkey,1,-3)
Tooltip % A_TickCount-time_down_%prefix%
return
Re: Global "anykey" hotkey for raw processing
The main idea of my multi-key hotkey Implementation is very simple, the down events of the keys adds a point for the sequence, any up event puts the score back to zero. Then, on full score, call some function. No timing, getkeystate or keywaiting required. It's just a matter of organising it.Exaskryz wrote:getting the time when the key is released after a KeyWait. The trouble is with threading though, as I'm not sure how pressing 4 hotkeys down and releasing them affects how the KeyWait is done.
Re: Global "anykey" hotkey for raw processing
Thank you both for the thoughts on this topic. I was kind of hoping there was some undocumented view into the key events processed under the hood. Absent that, your thought Exaskryz, about stacking labels was the best that I had come up with too. I'm basically implementing something very close to what you propose, but as Helgef points out, without the keywait line.
I'm still polishing the code, but the way I've got it working now is as follows... the firing of the keydown events store a tickcount in the timedown[key] place in the object, but only if it didn't previously exist. When the key up event comes, the delta is calculated and the object key is removed, allowing for recording time down for a future key down of that key. Basically, I have to protect against the repetitive fires of the keydown event while a key is being held down, but without using keywait. The checking for the blank object element seems to do the trick for that... at least so far.
Thank you both again for your help!
I'm still polishing the code, but the way I've got it working now is as follows... the firing of the keydown events store a tickcount in the timedown[key] place in the object, but only if it didn't previously exist. When the key up event comes, the delta is calculated and the object key is removed, allowing for recording time down for a future key down of that key. Basically, I have to protect against the repetitive fires of the keydown event while a key is being held down, but without using keywait. The checking for the blank object element seems to do the trick for that... at least so far.
Thank you both again for your help!
Re: Global "anykey" hotkey for raw processing Topic is solved
Lexikos, if you read this, is there any undocumented programmatic access to the key list that one can see in the "Ctrl-K List" in the AHK window? I've implemented a solution to my particular chorded-input problem (assisted by the kind folks above in this post) that logs a lot info that duplicates whatever is already in that key list data structure... Is there any way to read the key list already tracked by AHK? If not, no big deal, but I was hoping there might be some little-known way to access it... Thanks!
Btw... I'm talking about this list:
Btw... I'm talking about this list:
Code: Select all
VK SC Type Up/Dn Elapsed Key Window
-------------------------------------------------------------------------------------------------------------
72 03D u 0.08 F3
A2 01D d 5.66 LControl
46 021 d 0.11 f
46 021 u 0.11 f Find and Replace
A2 01D u 0.89 LControl
1B 001 d 0.22 Escape
1B 001 u 0.06 Escape Microsoft Excel
Re: Global "anykey" hotkey for raw processing
See ScriptInfo().
Altenratively: Most of the information in the KeyHistory entries comes from the keyboard hook. You can install your own (SetWindowsHookEx, WH_KEYBOARD_LL) and use GetKeyName to get the key names.
Altenratively: Most of the information in the KeyHistory entries comes from the keyboard hook. You can install your own (SetWindowsHookEx, WH_KEYBOARD_LL) and use GetKeyName to get the key names.
Re: Global "anykey" hotkey for raw processing
Thanks. ScriptInfo() is just what I was looking for but didn't find in my initial search. I appreciate the help, everyone!