AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

releasing modifier keys by means of send {X up} + BlockInput

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
arbe



Joined: 12 Apr 2005
Posts: 30

PostPosted: Tue Mar 13, 2007 4:53 pm    Post subject: releasing modifier keys by means of send {X up} + BlockInput Reply with quote

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
View user's profile Send private message
YMP



Joined: 23 Dec 2006
Posts: 265
Location: Russia

PostPosted: Wed Mar 14, 2007 6:53 am    Post subject: Reply with quote

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:
Code:

+F11:: Send, a

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
View user's profile Send private message
arbe



Joined: 12 Apr 2005
Posts: 30

PostPosted: Wed Mar 14, 2007 8:48 am    Post subject: Reply with quote

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
View user's profile Send private message
YMP



Joined: 23 Dec 2006
Posts: 265
Location: Russia

PostPosted: Wed Mar 14, 2007 9:56 am    Post subject: Reply with quote

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
View user's profile Send private message
arbe



Joined: 12 Apr 2005
Posts: 30

PostPosted: Wed Mar 14, 2007 11:33 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group