 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
arbe
Joined: 12 Apr 2005 Posts: 30
|
Posted: Tue Mar 13, 2007 4:53 pm Post subject: releasing modifier keys by means of send {X up} + BlockInput |
|
|
Hi AHK community!
I am writing a script that needs to be launched via a Ctrl+Shift+N hotkey. However, inside the script I need to perform keyboard and mouse action that only succeeds in my target application when no modifier key is pressed. Can you help me to come up with a reasonable solution to release the Ctrl and Shift modifier keys?
Using sendinput instead of sendevent won't work in my case since there are other AHK scripts with the keyboardhook installed (Chris writes in the documentation that in this case sendinput falls back to sendevent). The trivial solution of KeyWait Ctrl and KeyWait Shift is not desired either since I need my users to be able to hold down the modifiers for a while and launch several iterations of the script by continously pressing N.
I think there must be another solution that builds on this idea:
| Code: | #singleinstance force
#InstallKeybdHook ; important in order for physical keystate detection to work
^+n::
BlockInput On
releaseAllModifiers()
sleep 500
; this is where my automation action depends on all modifier keys to be released
showModifierState()
sleep 500
BlockInput Off
restoreModifierPhysicalState()
return
releaseAllModifiers()
{
list = LControl|RControl|LShift|RShift
Loop Parse, list, |
{
if (GetKeyState(A_LoopField))
send {%A_LoopField% up}
}
}
showModifierState()
{
list = LControl|RControl|LShift|RShift
output=
Loop Parse, list, |
output .= A_LoopField . ": " . GetKeyState(A_LoopField) . " (logical), " . GetKeyState(A_LoopField, "P") . " (physical)`n"
msgbox, , , %output%, 3 ; since blockinput is still in effect, automatically close this dialog after 3 seconds
}
restoreModifierPhysicalState()
{
list = LControl|RControl|LShift|RShift
Loop Parse, list, |
{
if (GetKeyState(A_LoopField) != GetKeyState(A_LoopField, "P")) ;if logical and physical state do not match
{
if (GetKeyState(A_LoopField, "P")) ;send an event to restore the physical key state
send {%A_LoopField% down}
else
send {%A_LoopField% up}
}
}
}
|
Here, I use blockinput to be sure that it doesn't matter, when the user physically releases the modifier keys. Then, I try to release the modifiers programmatically, if they are logically down. This is the spot that seems not to work. Do you have an idea other than sending {LControl up} in cases, where LControl is logically down? When my script finishes and I re-allow user input, I restore the physical keystate of the modifier keys. This is in order to enable continously pressed modifiers and to prevent sticky modifier keys (which I experience from time to time). This second part of the modifier key state tampering works smoothly on my WinXP SP2 with AHK 1.0.46.09.
Summing up, my problem is that the send key-up events of releaseAllModifiers() do not release the key logically -- as shown by showModifierState(). |
|
| Back to top |
|
 |
YMP
Joined: 23 Dec 2006 Posts: 265 Location: Russia
|
Posted: Wed Mar 14, 2007 6:53 am Post subject: |
|
|
What exactly does your "keyboard and mouse action" consist of? If it uses the Send command, then I see no problem here. The Send command automatically releases all modifiers before executing and restores them afterwards.
For example, this hotkey will send a lowercase "a" in spite of the fact that Shift is still down when it's sent:
If you look in the key history of the script above, you'll see what I'm talking about.
Mouse clicks also can be sent this way through
| Code: |
Send, {Click}
Send, {Click Right}
; And so on.
|
|
|
| Back to top |
|
 |
arbe
Joined: 12 Apr 2005 Posts: 30
|
Posted: Wed Mar 14, 2007 8:48 am Post subject: |
|
|
YMP,
thanks for your thoughts.
Using the send command's capability of releasing modifiers is not enough in my case. I am dragging an object across the screen which is dropped by the application as soon as there are modifier keys pressed (not only at pick up and dropping, but in the middle of the drag as well). I agree that this app is rather programmed against all conventions, but it is the way it is and I have to deal with it.
Did you test my code above? Did the MessageBox inside showModifierState() also reveal that the modifiers are always logically down?
I wonder why send {LControl up} doesn't release this modifier logically. I even tried to send another full down-up key-press (since the AHK keyhistory reveals this technique quite often). |
|
| Back to top |
|
 |
YMP
Joined: 23 Dec 2006 Posts: 265 Location: Russia
|
Posted: Wed Mar 14, 2007 9:56 am Post subject: |
|
|
| arbe wrote: |
Did the MessageBox inside showModifierState() also reveal that the modifiers are always logically down?
|
Yes, it did. Also if I held the modifiers a little longer when pressing +^n, I saw it in the message that the physical states were also 1.
I can't say I fully understand the whole mechanism underlying all this logical/physical matter. Just intuitively, I changed the releasing function to this:
| Code: |
releaseAllModifiers()
{
list = LControl|RControl|LShift|RShift
Loop Parse, list, |
{
if (GetKeyState(A_LoopField))
send {Blind}{%A_LoopField% up} ; {Blind} is added.
}
}
|
Now the message box reports 0 for the logical states. Try if it works for you. Perhaps it could be of some use for your purpose. |
|
| Back to top |
|
 |
arbe
Joined: 12 Apr 2005 Posts: 30
|
Posted: Wed Mar 14, 2007 11:33 am Post subject: |
|
|
YMP,
thank you so much for your help! My first tests show that send {Blind} is probably the solution I have been looking for for two days! |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|