AutoHotkey Community

It is currently May 26th, 2012, 10:46 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 71 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
 Post subject:
PostPosted: September 16th, 2009, 8:31 pm 
Offline

Joined: December 1st, 2008, 12:34 pm
Posts: 49
Location: UK
Thanks for the useful pointer to the Input command. I'd never really noticed it before, so time well spent playing around with it.

I had to alter the logic a bit to make your example work properly with both character and non-character keys. Mostly I was testing with LCtrl as the hotkey, and where the spurious key could be say LShift. LAlt, or nearby letter keys. (I've left your script in the test version below in case you want to compare).

I think the version in the script here does the job well enough, although it's still possible to defeat it with very fast typing. If I send say LCtrl-Shift-LCtrl very fast it should never register a double hit, yet occasionally it does whereas the 'do-nothing hotkeys' approach seems bomb-proof. I'll see how the new version works out in daily use.

Code:
;;;;;;;;;;;;;;;;;;;
; Modified versions of RapidHotkey() and Morse() to eliminate false alarms.
; Modifications by DAT, 16-09-2009, based on Laszlo's 15-09-2009 suggestions.
;
; The Issue:
; If you're using RapidHotkey to detect multiple hits on keys such
; Control, Shift, and Alt, to do things like opening search windows,
; the script tries to ensure no false alarms during normal typing. 
;
; Test:
; Action1 happens for single keypress of the right control key,
; Action2 for double press, and so on.
; If you change the parameters in RapidHotkey() to say,
; ("Action1""Action2""Action3""Action4",2,0.3,1), then Action1
; happens for double keypress and Action2 for triple, and so on.

Pip = 75
Tone = 2000

+Backspace::MsgBox % "Morse press pattern " Morse()     ; Laszlo's example
#!z::MsgBox % "Morse press pattern " Morse()            ; Laszlo's example

~LControl::RapidHotkey("Action1""Action2""Action3""Action4",1,0.3,1)

Action1:
Peep(1)
Return

Action2:
Peep(2)
Return

Action3:
Peep(3)
Return

Action4:
Peep(4)
Return

Peep(Rpts) {
   Global 
   Loop , %Rpts% {
      SoundBeep , %Tone% , %Pip%
      sleep, %pip%
   }
   Return
}

;;;;;;;;;;;;;;;;;;;;
/*
RapidHotkey() is unchanged from 24.02.2009 version posted by
Hotkeyit at
http://www.autohotkey.com/forum/viewtopic.php?t=38795.

Morse() is based on Laszlo's Morse() function at
http://www.autohotkey.com/forum/viewtopic.php?t=16951. The morse aspect is not
used - it just has to detect multiple hits of the same key that are
separated by less than 'timeout', returning 0 for one hit, 00 for two,
and so on. It returns blank if any other key is detected during what would
otherwise count as a multiple key-press. 

*/
RapidHotkey(keystroke, times="1", delay=0.2, IsLabel=0)
{
   Pattern := Morse(delay*1000)
   If (StrLen(Pattern) < 2 and Chr(Asc(times)) != "1")
      Return
   If (times = "" and InStr(keystroke, """"))
   {
      Loop, Parse, keystroke,""   
         If (StrLen(Pattern) = A_Index+1)
            continue := A_Index, times := StrLen(Pattern)
   }
   Else if (RegExMatch(times, "^\d+$") and InStr(keystroke, """"))
   {
      Loop, Parse, keystroke,""
         If (StrLen(Pattern) = A_Index+times-1)
            times := StrLen(Pattern), continue := A_Index
   }
   Else if InStr(times, """")
   {
      Loop, Parse, times,""
         If (StrLen(Pattern) = A_LoopField)
            continue := A_Index, times := A_LoopField
   }
   Else if (times = "")
      continue = 1, times = 2
   Else if (times = StrLen(Pattern))
      continue = 1
   If !continue
      Return
   Loop, Parse, keystroke,""
      If (continue = A_Index)
         keystr := A_LoopField
   Loop, Parse, IsLabel,""
      If (continue = A_Index)
         IsLabel := A_LoopField
   hotkey := RegExReplace(A_ThisHotkey, "[\*\~\$\#\+\!\^]")
   IfInString, hotkey, %A_Space%
      StringTrimLeft, hotkey,hotkey,% InStr(hotkey,A_Space,1,0)
   Loop % times
      backspace .= "{Backspace}"
   keywait = Ctrl|Alt|Shift|LWin|RWin
   Loop, Parse, keywait, |
      KeyWait, %A_LoopField%
   If ((!IsLabel or (IsLabel and IsLabel(keystr))) and InStr(A_ThisHotkey, "~") and !RegExMatch(A_ThisHotkey
   , "i)\^[^\!\d]|![^\d]|#|Control|Ctrl|LCtrl|RCtrl|Shift|RShift|LShift|RWin|LWin|Escape|BackSpace|F\d\d?|"
   . "Insert|Esc|Escape|BS|Delete|Home|End|PgDn|PgUp|Up|Down|Left|Right|ScrollLock|CapsLock|NumLock|AppsKey|"
   . "PrintScreen|CtrlDown|Pause|Break|Help|Sleep|Browser_Back|Browser_Forward|Browser_Refresh|Browser_Stop|"
   . "Browser_Search|Browser_Favorites|Browser_Home|Volume_Mute|Volume_Down|Volume_Up|MButton|RButton|LButton|"
   . "Media_Next|Media_Prev|Media_Stop|Media_Play_Pause|Launch_Mail|Launch_Media|Launch_App1|Launch_App2"))
      Send % backspace
   If (WinExist("AHK_class #32768") and hotkey = "RButton")
      WinClose, AHK_class #32768
   If !IsLabel
      Send % keystr
   else if IsLabel(keystr)
      Gosub, %keystr%
   Return
}


;/*

; ;;;;
;  DAT version based on Laszlo's suggestion of 15-09-2009 to use 'Input' but fettled
;  to work with character keys and non-character keys.
;
; 'Input' terminates with ErrorLevel=Max after one ('L1') input character,
; or with ErrorLevel=Timeout if it times out, or with ErrorLevel=EndKey:name if it
; detects one of the EndKeys. All the non-character keys used as hotkeys
; or recognisable as false hits must be listed as EndKeys in the Input command.
; Input doesn't put non-character keys into its output variable so false non-character
; keys are detected as EndKeys.
 
Morse(timeout = 400) {
   tout := timeout/1000
   key := RegExReplace(A_ThisHotKey,"[\*\~\$\#\+\!\^]") ; remove modifiers: +BS -> BS
   Loop
   {                            ; Loops until times out, or until spurious keypress intervenes.
      KeyWait %key%, T%tout%    ; Wait for key to be released.
      Pattern .= 0              ; appends 0 for each valid key-press in the multiple
     If(ErrorLevel)                       
         Return Pattern         ; Timed out, so finish.
      Input k , L1MT%tout%V , {LControl}{RControl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{BS}{Capslock}{Numlock}{PrintScreen}{Pause} 
      If (ErrorLevel="Timeout")
         Goto , End
      If ((k && k!=key) || !(k=key && Errorlevel="Max"|| !k && Errorlevel="EndKey:" key))
      {
         soundbeep , 300 , 20   ; beep on invalid key.
         Pattern =
         Goto , End
      }
   }
   End:
   ToolTip , key=%key%`nErrorLevel=%ErrorLevel%`nk=%k%`nPattern=%Pattern%
   Return Pattern
}
;*/

/*
;  Laszlo's 15-09-2009 11:10 example

Morse(timeout = 400) {
   tout := timeout/1000
   key := RegExReplace(A_ThisHotKey,"[\*\~\$\#\+\!\^]") ; remove modifiers: +BS -> BS
   Loop {
      t := A_TickCount
      KeyWait %key%                      ; Wait for key release
      Pattern .= A_TickCount-t > timeout ; How long the key was pressed
     
     Input k,L1MT%tout%V,{LControl}{RControl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{BS}{Capslock}{Numlock}{PrintScreen}{Pause}
      If (ErrorLevel && ErrorLevel != "Max" && ErrorLevel != "EndKey:" key
        || !ErrorLevel && k != key)     ; Break at long no-press time or foreign keys
         Return Pattern
   }
}
*/


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 16th, 2009, 11:15 pm 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
The issue is fixed now, so incorrect keys are detected :D

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun :wink:


Last edited by HotKeyIt on September 19th, 2009, 11:00 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 16th, 2009, 11:21 pm 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
DAT: "k && k!=key" could fail if the monitored key is the "0".

HotKeyIt: It seems to work, but could you do it with fewer loops, with less CPU load?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 17th, 2009, 2:39 pm 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
Laszlo wrote:
HotKeyIt: It seems to work, but could you do it with fewer loops, with less CPU load?


Sure, see top post :D

Though Morse is now huge, it looks to work very well.
I have also made it to work for hotkeys like:
Code:
 +::RapidHotkey(...
#::MsgBox % Morse(200)


Please note, my Morse() version does not detect long key presses :!:

Enjoy ;)

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun :wink:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 17th, 2009, 3:32 pm 
Offline

Joined: December 1st, 2008, 12:34 pm
Posts: 49
Location: UK
Quote:
The issue is fixed now, so incorrect keys are detected

Shucks, I was quite enjoying meddling with it!
Seriously though, thanks for the script and the fix. I use it on LCtrl so false alarms were getting to be annoying. Now to try and understand how it works...

Message edit 17-09-2009 16:40:
I wrote the above before testing it. I've since tried it out using the same test setup I used for mine (see earlier post). At first it didn't work properly. Typing LCtrl-c-LCtrl (LCtrl as the hotkey) registered as a double hit every time whereas most times LCtrl-RShift-LCtrl did not.

Then the penny dropped - I'm typing too fast for it :(; it's ok when I type slowly but not rapidly. I tried to estimate the critical speed using Key History. Can't tell exactly, but with a character as the spurious key, a 190ms gap between keys is ok and 90ms isn't.

Sorry to bring bad news ...


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 17th, 2009, 6:02 pm 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
Hi DAT,

I have tried to reproduce the error using your example and in 99.9% it really works for me :?

Can you try to change following lines and tell me what you get:?:
Code:
KeyWait %key%, T0.03
;to
KeyWait %key%, T0.02 ;or even KeyWait %key%, T0.01
;and
KeyWait %key%, T0.03
;to
KeyWait %key%, DT0.02
;you can also try to use
SetBatchLines,-1

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun :wink:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 17th, 2009, 7:00 pm 
Offline

Joined: December 1st, 2008, 12:34 pm
Posts: 49
Location: UK
Answering in haste else late for a band practice ...

I changed KeyWait %key%, T0.03 to 0.01 and KeyWait %key%, DT0.03 to DT0.02 but no noticeable improvement.

Then I added SetBatchLines,-1 but again no obvious change with character keys. However after all that I can't seem to fool it with RShift, LShift, Alt. But I can with CapsLock and character keys (easily).

Some keys definitely worse than others. For example it now detects RShift, LShift, Alt as spurious every time, but I can easily fool it with CapsLock. CapsLock seems about as bad as all the character keys.

Anyway must rush. Good luck... Back about 23:00.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 17th, 2009, 9:24 pm 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
Can you try again function from top post?

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun :wink:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 17th, 2009, 11:21 pm 
Offline

Joined: December 1st, 2008, 12:34 pm
Posts: 49
Location: UK
Quote:
Can you try again function from top post?

I've done this. It works fine for nearly all the non-character keys including CapsLock. The only exceptions are PrtScr, Pause, and Spacebar. These behave like the character keys and they escape the trap unless I type slower. In a sequence like Ctrl-c-Ctrl, the first gap can be very short; it's the second gap that's critical.

Strange you don't see the effect. Could it be your keyboard has a slower action or your computer is faster? I'm using a Toshiba M5 laptop with 2.16GHz dual-core CPU. Seems pretty fast in normal use (especially since I put an Intel SSD in it :) ).


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 18th, 2009, 5:42 am 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
My computed is definitely slower and I can't reproduce that behaviour :?
So when you press Ctrl - c - Ctrl in following script you definitely get 2 beeps?
Code:
~LCtrl::RapidHotkey("b1""b2""b3""b4",1,0.2,1)
b1:
b2:
b3:
b4:
SoundBeep,% SubStr(A_ThisLabel,0)*1000,100
Return


For me pressing Ctrl - c - Ctrl beeps only once, for the last Ctrl press which is correct. Can you close all other AHK scripts and try then.

Can you also try 1 second timeout.
Code:
~LCtrl::RapidHotkey("b1""b2""b3""b4",1,1,1)

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun :wink:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 18th, 2009, 12:44 pm 
Offline

Joined: December 1st, 2008, 12:34 pm
Posts: 49
Location: UK
Tests done with version newly downloaded this morning.
Quote:
So when you press Ctrl - c - Ctrl in following script you definitely get 2 beeps?

Definitely. (Well, to be exact, I get 2kHz beep instead of expected 1kHz)
Quote:
Can you close all other AHK scripts and try then.

Same result. Even closed all other programs except ones native to the computer - same result.

Quote:
Can you also try 1 second timeout.
~LCtrl::RapidHotkey("b1""b2""b3""b4",1,1,1)

Interesting. The long wait before a decision makes it easier to demonstrate. Now I can type in slow motion and beat it. With 2s delay it's even more apparent. I can do LControl<wait almost 1s>c<wait almost 1s>LControl and it registers a double-hit. Also, should it not give a result immediately it gets the spurious key instead of waiting for a further timeout period?

I hope you can repeat these slow-motion effects, otherwise there's something very queer going on :shock:

PS. Just in case, my AHK version is 1.0.48.3.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 19th, 2009, 10:59 am 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
I have made some changes again.
It is now using loops again but with less CPU load?

DAT, can you try again?

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun :wink:


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 19th, 2009, 11:28 am 
Offline

Joined: December 1st, 2008, 12:34 pm
Posts: 49
Location: UK
Great. Just tried it and it seems much better. This is not a true test though because I'm away from home until Sunday so I'm using a different laptop (Tosh R500 running Vista not XP as before).

Will try more rigorously later but so far big improvement I think as I can't seem to fool it at all so far. :D


Edit 20-09-2009 21:26
I've now tried your 19.09.2009 version on the original XP computer and, as on the Vista machine, it works fine without false alarms even when typing very quickly. Thanks a lot for sorting it out.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: First label speed
PostPosted: May 13th, 2010, 8:18 pm 
Offline

Joined: May 7th, 2010, 7:40 pm
Posts: 9
Location: Italy
Ok
I have an script with rapidhotkey functions where i remaped all keys on keyboard for cirilic use. I have a problem with two lebels parameters as definition is for both labels. My question is if there is posibility to have first label without time delay and second under time delay. Thanks in advance!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 13th, 2010, 8:54 pm 
Offline

Joined: June 18th, 2008, 8:36 am
Posts: 4923
Location: AHK Forum
You can do it as following:
Code:
$a::
Send a
RapidHotkey("{BackSpace}b""{BackSpace}c")
Return

_________________
AHK_H (2alpha) AHF TT _Struct WatchDir Yaml _Input ObjTree RapidHotkey DynaRun :wink:


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 71 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: fragman, jrav, Yahoo [Bot] and 14 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group