Pressing a key twice quickly to trigger a function in AutoHotKey - windows

I want to bind 'jj' to Esc using AutoHotkey in my Rstudio application. Is there any way we can map 'jj' to trigger Escape in a selected windows application?

I found a solution, that worked.
#IfWinActive ahk_exe rstudio.exe
l::
{
count++
settimer, actions, 150
}
return
actions:
{
if (count = 1)
{
Send j
}
else if (count = 2)
{
Send {Esc}
}
count := 0
}
return

Related

Is there a way to make multiple windows "active" at one time? in Windows?

Let's say a program that I created, an on-screen keyboard. I want to make it active so that it can receive my keyboard inputs, even while another program such as Google Chrome, or Notepad.exe is receiving my keyboard inputs as well. I mainly want my keyboard to run like "Nohboard" I am having trouble because once I get my keyboard looking and working like I want it, whenever I open another window, my keyboard will not work as long as "Windows 7" is focused on the "notepad.exe" for example. The reason I am making this is to monitor my keystrokes on-screen using my own software. I am trying to design my keyboard with gm studio 1.4 but without having the ability to make multiple windows active at once, my keyboard becomes useless everytime I click away from the keyboard program that I can create.
Is there any workarounds that can be used? Maybe a 3rd party script created by another program to allow my program's window to be "active" and receive keyboard keystroke inputs while another program is also active and receiving keyboard keystroke inputs?
Thanks in advance for anyone who can think of a solution that would be at all helpful.
Space::
SetTitleMatchMode, 2
ControlSend, , {Space Down}, Typing Lessons
ControlSend, , {Space Down}, kb
Keywait, Space
ControlSend, , {Space Up}, kb
ControlSend, , {Space Up}, Typing Lessons
Return
One thing that I've just figured out how to do, with autohotkey scripts is send keys to multiple programs. Is there a way to send it to the "last active window" and the "current active window" using autohotkey?
On a Windows System it is not possible to activate Multiple Windows at the same Time.
Only One Window can be Active. (Focused)
But there are two Ways that can help to Solved your Problem.
1 - You can for example your Onscreen Keyboard Window, to let ignore/disable Focus that Keyboard Window. (No Focus) (No activate + +E0x08000000)
Try This Ahk Script.
Note: This is a onscreen Keys Strip from F1 to F12
Example1.ahk
Gui, +LastFound +AlwaysOnTop +ToolWindow -Caption +Border +E0x08000000
Gui, Font, s07, Arial
Loop, 12
Gui, Add, Button, % "x" 5+(A_Index-1)*60 " y5 w60 h25 vF" A_Index " gButton", F%A_Index%
Gui, Show, y0 w730 h35 NoActivate
Return
Button:
SendInput, % "{" A_GuiControl "}"
Return
GuiClose:
ExitApp
Return
~esc::exitapp
2 - Or You can Use a 3rd party script,
note : run these 2 Scripts together. (KeypressValueToREG + ShowKeypressValue)
The First one is a Large Script but you can do many things, It Will Put All your Mouse and Keyboard Movements into Only One Windows Registry Key.
The Power of this KeypressValueToREG script is, you can run it in the background, and then you can use it in other Applications or other Languages Visual Studio/Visual Basic/c++/Python/Autohotkey/? They only need to Acces/Read that One Registry Key.
KeypressValueToREG.ahk
;KeypressValueToREG.ahk comes from KeypressOSD.ahk that was Created by Author RaptorX
; Open this Script in Wordpad and For Changelog look to the Bottom of the script.
;This code works with a getkeyname from a Dllcall (See Bottom Script- by Lexikos)
;you can press the esc key to exit.
#SingleInstance force
#NoEnv
SetBatchLines, -1
ListLines, Off
; Settings
global TransN := 200 ; 0~255
global ShowSingleKey := True
global ShowMouseButton := True
global ShowSingleModifierKey := True
global ShowModifierKeyCount := true
global ShowStickyModKeyCount := false
global DisplayTime := 2000 ; In milliseconds
global GuiPosition := "Bottom" ; Top or Bottom
global FontSize := 50
global GuiHeight := 115
CreateGUI()
CreateHotkey()
return
OnKeyPressed:
try {
key := GetKeyStr()
ShowHotkey(key)
SetTimer, HideGUI, % -1 * DisplayTime
}
return
OnKeyUp:
return
_OnKeyUp:
tickcount_start := A_TickCount
return
CreateGUI() {
global
Gui, +AlwaysOnTop -Caption +Owner +LastFound +E0x20
Gui, Margin, 0, 0
Gui, Color, Black
Gui, Font, cWhite s%FontSize% bold, Arial
Gui, Add, Text, vHotkeyText Center y20
WinSet, Transparent, %TransN%
}
CreateHotkey() {
Loop, 95
{
k := Chr(A_Index + 31)
k := (k = " ") ? "Space" : k
Hotkey, % "~*" k, OnKeyPressed
Hotkey, % "~*" k " Up", _OnKeyUp
}
Loop, 24 ; F1-F24
{
Hotkey, % "~*F" A_Index, OnKeyPressed
Hotkey, % "~*F" A_Index " Up", _OnKeyUp
}
Loop, 10 ; Numpad0 - Numpad9
{
Hotkey, % "~*Numpad" A_Index - 1, OnKeyPressed
Hotkey, % "~*Numpad" A_Index - 1 " Up", _OnKeyUp
}
Otherkeys := "WheelDown|WheelUp|WheelLeft|WheelRight|XButton1|XButton2|Browser_Forward|Browser_Back|Browser_Refresh|Browser_Stop|Browser_Search|Browser_Favorites|Browser_Home|Volume_Mute|Volume_Down|Volume_Up|Media_Next|Media_Prev|Media_Stop|Media_Play_Pause|Launch_Mail|Launch_Media|Launch_App1|Launch_App2|Help|Sleep|PrintScreen|CtrlBreak|Break|AppsKey|NumpadDot|NumpadDiv|NumpadMult|NumpadAdd|NumpadSub|NumpadEnter|Tab|Enter|Esc|BackSpace"
. "|Del|Insert|Home|End|PgUp|PgDn|Up|Down|Left|Right|ScrollLock|CapsLock|NumLock|Pause|sc145|sc146|sc046|sc123"
Loop, parse, Otherkeys, |
{
Hotkey, % "~*" A_LoopField, OnKeyPressed
Hotkey, % "~*" A_LoopField " Up", _OnKeyUp
}
If ShowMouseButton {
Loop, Parse, % "LButton|MButton|RButton", |
Hotkey, % "~*" A_LoopField, OnKeyPressed
}
for i, mod in ["Ctrl", "Shift", "Alt"] {
Hotkey, % "~*" mod, OnKeyPressed
Hotkey, % "~*" mod " Up", OnKeyUp
}
for i, mod in ["LWin", "RWin"]
Hotkey, % "~*" mod, OnKeyPressed
}
ShowHotkey(HotkeyStr) {
WinGetPos, ActWin_X, ActWin_Y, ActWin_W, ActWin_H, A
if !ActWin_W
throw
text_w := (ActWin_W > A_ScreenWidth) ? A_ScreenWidth : ActWin_W
;remove this gui codeline if you want only to Write the Value to Windows registry
;GuiControl, , HotkeyText, %HotkeyStr%
;GuiControl, , HotkeyText, %HotkeyStr%
RegWrite, REG_SZ, HKEY_CURRENT_USER,software\GetKeypressValue,KeypressValue,%HotkeyStr%
;remove this gui codeline if you want only to Write the Value to Windows registry
;GuiControl, Move, HotkeyText, w%text_w% Center
;GuiControl, Move, HotkeyText, w%text_w% Center
if (GuiPosition = "Top")
gui_y := ActWin_Y
else
gui_y := (ActWin_Y+ActWin_H) - 115 - 50
;remove this gui codeline if you want only to Write the Value to Windows registry
;Gui, Show, NoActivate x%ActWin_X% y%gui_y% h%GuiHeight% w%text_w%
;Gui, Show, NoActivate x%ActWin_X% y%gui_y% h%GuiHeight% w%text_w%
}
GetKeyStr() {
static modifiers := ["Ctrl", "Shift", "Alt", "LWin", "RWin"]
static repeatCount := 1
for i, mod in modifiers {
if GetKeyState(mod)
prefix .= mod " + "
}
if (!prefix && !ShowSingleKey)
throw
key := SubStr(A_ThisHotkey, 3)
if (key ~= "i)^(Ctrl|Shift|Alt|LWin|RWin)$") {
if !ShowSingleModifierKey {
throw
}
key := ""
prefix := RTrim(prefix, "+ ")
if ShowModifierKeyCount {
if !InStr(prefix, "+") && IsDoubleClickEx() {
if (A_ThisHotKey != A_PriorHotKey) || ShowStickyModKeyCount {
if (++repeatCount > 1) {
prefix .= " ( * " repeatCount " )"
}
} else {
repeatCount := 0
}
} else {
repeatCount := 1
}
}
} else {
if ( StrLen(key) = 1 ) {
key := GetKeyChar(key, "A")
} else if ( SubStr(key, 1, 2) = "sc" ) {
key := SpecialSC(key)
} else if (key = "LButton") && IsDoubleClick() {
key := "Double-Click"
}
_key := (key = "Double-Click") ? "LButton" : key
static pre_prefix, pre_key, keyCount := 1
global tickcount_start
if (prefix && pre_prefix) && (A_TickCount-tickcount_start < 300) {
if (prefix != pre_prefix) {
result := pre_prefix pre_key ", " prefix key
} else {
keyCount := (key=pre_key) ? (keyCount+1) : 1
key := (keyCount>2) ? (key " (" keyCount ")") : (pre_key ", " key)
}
} else {
keyCount := 1
}
pre_prefix := prefix
pre_key := _key
repeatCount := 1
}
return result ? result : prefix . key
}
SpecialSC(sc) {
static k := {sc046: "ScrollLock", sc145: "NumLock", sc146: "Pause", sc123: "Genius LuxeMate Scroll"}
return k[sc]
}
; by Lexikos - https://autohotkey.com/board/topic/110808-getkeyname-for-other-languages/#entry682236
GetKeyChar(Key, WinTitle:=0) {
thread := WinTitle=0 ? 0
: DllCall("GetWindowThreadProcessId", "ptr", WinExist(WinTitle), "ptr", 0)
hkl := DllCall("GetKeyboardLayout", "uint", thread, "ptr")
vk := GetKeyVK(Key), sc := GetKeySC(Key)
VarSetCapacity(state, 256, 0)
VarSetCapacity(char, 4, 0)
n := DllCall("ToUnicodeEx", "uint", vk, "uint", sc
, "ptr", &state, "ptr", &char, "int", 2, "uint", 0, "ptr", hkl)
return StrGet(&char, n, "utf-16")
}
IsDoubleClick(MSec = 300) {
Return (A_ThisHotKey = A_PriorHotKey) && (A_TimeSincePriorHotkey < MSec)
}
IsDoubleClickEx(MSec = 300) {
preHotkey := RegExReplace(A_PriorHotkey, "i) Up$")
Return (A_ThisHotKey = preHotkey) && (A_TimeSincePriorHotkey < MSec)
}
HideGUI() {
Gui, Hide
}
~esc::exitapp
;---------------------------------------------
; ChangeLog : v2.22 (2017-02-25) - Now pressing the same combination keys continuously more than 2 times,
; for example press Ctrl+V 3 times, will displayed as "Ctrl + v (3)"
; v2.21 (2017-02-24) - Fixed LWin/RWin not poping up start menu
; v2.20 (2017-02-24) - Added displaying continuous-pressed combination keys.
; e.g.: With CTRL key held down, pressing K and U continuously will shown as "Ctrl + k, u"
; v2.10 (2017-01-22) - Added ShowStickyModKeyCount option
; v2.09 (2017-01-22) - Added ShowModifierKeyCount option
; v2.08 (2017-01-19) - Fixed a bug
; v2.07 (2017-01-19) - Added ShowSingleModifierKey option (default is True)
; v2.06 (2016-11-23) - Added more keys. Thanks to SashaChernykh.
; v2.05 (2016-10-01) - Fixed not detecting "Ctrl + ScrollLock/NumLock/Pause". Thanks to lexikos.
; v2.04 (2016-10-01) - Added NumpadDot and AppsKey
; v2.03 (2016-09-17) - Added displaying "Double-Click" of the left mouse button.
; v2.02 (2016-09-16) - Added displaying mouse button, and 3 settings (ShowMouseButton, FontSize, GuiHeight)
; v2.01 (2016-09-11) - Display non english keyboard layout characters when combine with modifer keys.
; v2.00 (2016-09-01) - Removed the "Fade out" effect because of its buggy.
; - Added support for non english keyboard layout.
; - Added GuiPosition setting.
; v1.00 (2013-10-11) - First release.
;--------------------------------------------
And the Second One it will Show Visual On your Desktop Screen All your Mouse and Keyboard Movements, You can Change this Script a little bit and then make your own keyboard that can show Visual all your keyboard Movements,
and if you use the trick from Example1.ahk then you can make a Professional Onscreen Keyboard Without focus the Window.
ShowKeypressValue.ahk
#SingleInstance force
Gui, +AlwaysOnTop -MaximizeBox ; -Caption +Resize -MinimizeBox +Disabled -SysMenu -Owner +OwnDialogs
Gui, Add, Text, center y10 h50 w300 vVar, %KeypressValue%
Gui, Color, White
Gui, show
size=20
Gui, Font, s%size%
GuiControl, Font, var
;run KeypressValueToREG.ahk - together with ShowKeypressValue.ahk
;The Features Are:
; - It will Show On your Screen, [All your Mouse Movements] and [All Keyboard Shortcuts Movement]
; - You can Make Scripts, that can do actions with MultiClicks on All Keyboard Shortcuts Clicks, How Cool Is that.
loop
{
RegRead, KeypressValue, HKEY_CURRENT_USER,software\GetKeypressValue,KeypressValue ; read KeypressValue
sleep 50
GuiControl,, var, %KeypressValue%
if (KeypressValue="Alt ( * 2 )") ;use this for [1x=Alt][2x=Alt ( * 2 )][3x=Alt ( * 3 )] [and many more]
{
;Here you can put any AHK CODE
msgbox you did click Alt 2x Times
}
if (KeypressValue="Alt ( * 3 )") ;use this for [1x=Alt][2x=Alt ( * 2 )][3x=Alt ( * 3 )] [and many more]
{
;Here you can put any AHK CODE
msgbox you did click Alt 3x Times
}
} ;End Loop
~esc::exitapp
Try this .
#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
#InstallKeybdHook
#UseHook
; Add the keys you want send to the last active window in this array:
Keys := ["a","b","c","1","2","3","space",",",".","-","_","F3"] ; ...
for each, key in Keys
Hotkey, %key%, send_key_to_last_active_window, on
SetTimer get_last_active_window, 300 ; you can decrease this period (number of milliseconds that pass before the timer is executed)
return
send_key_to_last_active_window:
Send, {%A_ThisHotkey%}
; WinGetTitle, Title, ahk_id %LastActive_ID%
; WinGetClass, Class, ahk_id %LastActive_ID%
; ToolTip, last_active_window=%Title% ahk_class %Class%,,, 2
; If Class in Notepad,WordPadClass ; if the last active window is Notepad or WordPad
ControlSend,, {%A_ThisHotkey%}, ahk_id %LastActive_ID%
return
get_last_active_window:
WinGet, CurrentActive_ID, ID, A
If (CurrentActive_ID != NewActive_ID)
{
LastActive_ID = %NewActive_ID%
NewActive_ID := CurrentActive_ID
; WinGetTitle, NewActiveTitle, ahk_id %NewActive_ID%
; WinGetTitle, LastActiveTitle, ahk_id %LastActive_ID%
SetTimer get_last_active_window, off
; CoordMode, ToolTip, Screen
; ToolTip, Current active window:`nTitle: %NewActiveTitle%`nID: %NewActive_ID%`n`nLast active window:`nTitle: %LastActiveTitle%`nID: %LastActive_ID%, 0, 0, 1
WinWaitNotActive, ahk_id %NewActive_ID%
SetTimer get_last_active_window, on
}
return
See For-Loop, Hotkey and SetTimer in the documentation.

How to get starting time of a File Explorer window?

I'm building Autohotkey script in order to take a backup of opened File Explorer windows list.
I'm looking for a way in order to get starting time of each window (time when I've opened the window).
I've this function:
list_opened_folders(byref file_explorer_windows) {
; file_explorer_windows := [] ; array of file_explorer_windows
for window in ComObjCreate("Shell.Application").Windows {
file_explorer_windows[a_index] := {}
file_explorer_windows[a_index].path := window.Document.Folder.Self.Path
file_explorer_windows[a_index].id := window.HWND
file_explorer_windows[a_index].started_time := window.Document.Folder.Self.Time ; Line I'm trying to add (I know this is invalid but to illustrate my idea)
}
}
Try:
#Persistent
DetectHiddenWindows, On
SetTitleMatchMode, 2
file_explorer_windows := {}
SetTimer, GetExplorer, 100
GetExplorer:
Process, Exist, Explorer.exe
If ErrorLevel
{
for window in ComObjCreate("Shell.Application").Windows {
if (file_explorer_windows[window.HWND]["id"] == "") {
file_explorer_windows[window.HWND] := {id: window.HWND
, path: window.Document.Folder.Self.Path
, start: A_NowUTC}
}
}
}
Return

how to fix my AutoHotkey active window checker (fileappend)

It is supposed to put an entry in a text file each time a new window is active, instead it constantly loops and puts thousands of entries while the window is active, if anyone is capable of rectifying this I would be grateful.
loop
{
if new_window = %window_title%
new_window = diff
else
{
WinGetActiveTitle, window_title
fileappend, %window_title%`n, C:\mydirectory\myname.txt
new_window = %window_title%
}
}
Any help able to be provided would be more than welcome.
This uses a timer to check for a new window every 0.5 seconds.
#Persistent
prev_window := ""
settimer, check_window, 500
return
check_window:
WinGetActiveTitle, active_window
if (active_window != prev_window) {
fileappend, %active_window%`n, myname.txt
prev_window := active_window
}
return
The same could be accomplished in a loop:
prev_window := ""
loop
{
WinGetActiveTitle, active_window
if (active_window != prev_window) {
fileappend, %active_window%`n, myname.txt
prev_window := active_window
}
sleep, 500
}
return
You should probably put a SetTimer that checks active window title in some time interval (100ms or something) and compare to previously checked window tile - and if it has changed then write to file.

Determine length of time keys are pressed

Can below script be modified so that the keys
"cl" fires "www.google.com" just if the "cl" keys
are both pressed for 500 milliseconds ?
Reason for this is that as part typing text sometimes the keys "cl" are pressed in rapid succession which then fires "www.google.com"
~l::
If (GetKeyState("c","p") && GetKeyState("l","p")) {
Send, {Backspace Down}{Backspace Up}{Backspace Down}{Backspace Up}
Run, "www.google.com"
}
Return
Using A_TickCount may be a good option.
~l::
duration := 0
If (GetKeyState("c","p") && GetKeyState("l","p"))
{
start := A_TickCount
While (GetKeyState("c") && GetKeyState("l"))
Sleep, 1
duration := A_TickCount - start
}
if (duration > 500)
Run, "www.google.com"
Return
This appears to do the trick :
~c::
~l::
If (GetKeyState("c","p") && GetKeyState("l","p")) {
Send, {Backspace Down}{Backspace Up}{Backspace Down}{Backspace Up}
sleep, 100
If (GetKeyState("c","p") && GetKeyState("l","p")) {
Run, "www.google.com"
}
Return
}
Return
Per this AutoHotKey forum post:
[T]he only way to program a key down for a specific duration is to use the down command and then a wait function with a (manually entered time) and then the up command[.]
So, you could solve this problem by putting a timer and then another if block inside your current if block, although it sounds like a bad idea.
A 500 millisecond delay could cause uncontrolled key repetition sothat we can't reliably delete the pressed keys anymore. So my suggestion is to find the repeat delay and only wait for so long minus ~150 milliseconds:
~c::
~l::
If (GetKeyState("c","p") && GetKeyState("l","p")) {
If (!GetKeyState("c","p") || !GetKeyState("l","p"))
Return
DllCall("SystemParametersInfo", UInt, 0x16, UInt, 0, UIntP, RepeatDelay, UInt, 0) ;get the key repeat delay
Sleep % (RepeatDelay+1)*250-150
If (GetKeyState("c","p") && GetKeyState("l","p")) {
SendInput, {c up}{l up}{BS}{BS}
Run, www.google.com
}
}
Return
SystemParametersInfo - SPI_GETKEYBOARDDELAY

Visual Studio Shortcutkeys

I was working on a project, and while pressing some shortcut keys, I noticed the status bar of Visual Studio 2010:
Please try some shortcuts yourself to notice the whole behavior of VS, and then...how could I achieve that effect at the same level of performance? Thanks in advance!
P.S. I have the following code block taken from Stack Overlow, that does something like that but not the same performacnce level. My code works for CTRL + K, P.
protected override bool ProcessCmdKey( ref Message msg, Keys keyData )
{
if (prefixSeen)
{
if (keyData == ( Keys.Control | Keys.P))
{
MessageBox.Show( "Got it!" );
keyComb.Text = "Ready";
}
prefixSeen = false;
return true;
}
if (keyData == ( Keys.Control | Keys.K))
{
prefixSeen = true;
keyComb.Text = "CTRL + K was pressed. Waiting for a second chord of keys...";
return true;
}
return base.ProcessCmdKey( ref msg, keyData );
}
But after pressing CTRL + K The label keyComb does not take the value "CTRL + K was pressed. Waiting for a second chord of keys..."
Code taken from: How to get a combination of keys in c#

Resources