Creating a Mouse Hotkey - autohotkey

I've been using AHK in a very simple form for years, but multiple attempts at learning the more advanced functions has just resulted in confusion and frustration.
At the moment I'm trying to create a script that'll send the hotkey "CTRL + W" to Google Chrome when I hold the tilde key and left click inside the Google Chrome window. Whenever I trigger the script, it seems to close every single tab then the browser itself.
My script is below - what am I doing wrong?
#IfWinActive ahk_class Chrome_WidgetWin_1 ;Checks that the active window is Google Chrome.
` & LButton:: ;Tilde + Left Mouse Button
Send, ^+w ;Sends CTRL + W to the window.
return ;Ends the script.

Your script looks almost right. Try this. After you defined all the keys, you must "close" #ifwinactive ...
#IfWinActive, ahk_class Chrome_WidgetWin_1
` & LButton::Send, ^+w
#IfWinActive
Splitting the hotkey over multiple lines in not wrong, but in this case it can be done in one line. When you run into a problem like this. Try to isolate the issues. First ONLY try a bare ' & LButton::Send X to see if this works and be aware that you now loose the ` sign. Then try it with ^+w and when that works try it with #IfWinActive.
When you want to "restore" the tilde key, you could add this line:
~`::Return
The ~ will pass on the key data to the OS before executing the NOP (Return).

Related

How to hold a modifier key so ahk sends keypresses to a different window

I'm pretty new to ahk.
Say I have two separate vlc windows open and playing videos.
If one of the vlc windows is active, then I want to be able to hold a key to make all keypresses go to the other vlc window.
ie if I press Left, then it sends Left to the active vlc window, but if I hold ALT+Left, then it sends Left to the other vlc window.
If no vlc window is active, then I don't want autohotkey to do anything.
This is so I can control two vlc windows without having to click and choose which one is active.
I looked up GroupAdd hoping I could use a group that includes both vlc windows, but couldn't find a way to target specific vlc windows from the group to send keys to it.
edit: I got a very basic version working, but I feel it's pretty ugly. I would like a way to send any key that's pressed if you hold Shift to the other vlc window. Also this seems a bit unreliable in switching focus if you use it a few times quickly in succession.
GroupAdd, vlcgroup, ahk_exe vlc.exe
return
#IfWinActive ahk_exe vlc.exe
+Left:: ; shift-left
GroupActivate, vlcgroup, r
Send {Left}
GroupActivate, vlcgroup, r
return
A simple approach could be done like this:
#IfWinActive, ahk_exe vlc.exe
+Left::
WinGet, WindowList, List, ahk_exe vlc.exe
BottomMostVlcHwnd := WindowList%WindowList%
ControlSend, , {Left}, % "ahk_id " BottomMostVlcHwnd
return
^+Left::
WinGet, WindowList, List, ahk_exe vlc.exe
BottomMostVlcHwnd := WindowList%WindowList%
ControlSend, , ^{Left}, % "ahk_id " BottomMostVlcHwnd
return
...
#IfWinActive
You'd write out each hotkey.
WinGet, , List(docs) returns a legacy pseudo-array(docs) of hwnds to Vlc windows.
The last element in that array will be the bottom most window.
You can get the last element of a pseudo array via a dynamic variable trick WindowList%WindowList%.
Essentially you're accessing a variable named WindowListN, where N is the number for the last element in the pseudo-array.
Then ControlSend(docs) is used to send keys to the background window without the need to activate it.
And you refer to the background window by a window name like ahk_id 0x1234567(docs).
Of course writing out the hotkey for each key is pretty repetitive, so we can do something much better:
#IfWinActive, ahk_exe vlc.exe
+Left::
^+Left::
+Right::
^+Right::
+PgUp::
+PgDn::
WinGet, WindowList, List, ahk_exe vlc.exe
ControlSend, , % StrReplace(A_ThisHotkey, "+", "{") "}", % "ahk_id " WindowList%WindowList%
return
#IfWinActive
The hotkey definitions are just stacked on top of each other.
(If there were even more definitions, a loop with the Hotkey(docs) command could be nicer)
A_ThisHotkey(docs) will contain the hotkey that was used, and StrReplace(docs) is used to automatically replace the + with a {.
And finally the closing brace } is appended to the end.

How to start a program if not already started, put on focus if already started?

I would like to make a ahk script to start apps if they are not currently started and maximize them if they are. Is it possible using AHK ?
CapsLock & w::
Run firefox.exe
Return
Something like this but make it so that if I press CapsLock & w and then minimize firefox, pressing CapsLock & w would bring it back maximized / in focus. Any ideas? Thanks!
Sure, this is very easy and doable with AHK.
Here's a very easy and straight forward example
CapsLock & w::
if (WinExist("ahk_exe notepad.exe"))
{
WinActivate, ahk_exe notepad.exe
WinMaximize, ahk_exe notepad.exe
}
else
Run, notepad.exe
return
ahk_exe (docs) is used to refer to windows by their process. It's very convenient.
The code that you are looking for is somewhat similar to the example they give in the docs for WinActivate
So modifying that example for your purpose, and adding conditionals would give you:
CapsLock & w::
if WinExist("ahk_exe firefox.exe")
if WinActive("ahk_exe firefox.exe")
WinMinimize
else
WinActivate
else
Run firefox.exe
Return
Take note that this script will currently only minimize a Firefox window if it is the currently active window. If you need it to minimize a Firefox in the background, the script would potentially be a bit more complex since you could possibly have multiple Firefox windows open, and you would need to provide conditions and logic to handle cases like those. However, if you need this functionality, describe what behavior you would like to occur if this condition occurs, and I can work on it.

WinActivate does not work as expected. Re-activating focus to the starting window

I am having some serious struggles fully grasping the control on activating windows and forcing their focus and foremost position.
In order to debug a larger script I made a separate script to test the use of WinActivate and again I am observing frustrating behaviour as it either all together ignores the title I have defined or is failing in some other way. In the smaller test script I am simply requesting that the window in which the hotkey was triggered be set as active after another action, specifically an input box
Below is the simple code for testing:
F10::
SetTitleMatchMode, 1
DetectHiddenWindows, Off
WinGetTitle, startTitle, A
msgbox % "Start Title = <" . startTitle . ">"
;WinActivate, startTitle
inputbox, mode, Test box, Testing,,260,160
sleep 500
WinActivate, startTitle
Return
This code does not properly activate the starting window. For example I execute the hotkey in an empty notepad window and upon submitting blank into the input box the focus becomes notepad++ on my second monitor. The second time I press the hotkey from within notepad (or another application) notepad does not lose focus. In a third execution I begin from notepad again and after the input box appears I switch the focus to another window. I again submit blank to the inputbox but that new window remains the focus and notepad is not activated or brought to the foremost position.
Can someone please explain to me what is going on with WinActivate?
I was having similar frustration with unexpected results making a windows script host file and I think I must be missing some fundamental detail in windows.
You are trying to activate a window that start with the literal text "startTitle".
You forgot(?) to either enter expression syntax with % or use the legacy way of referring to a variable %startTitle% (please don't use legacy).
Extra stuff:
You shouldn't specify SetTitleMatchMode and DetectHiddenWindows inside your hotkey statement. There is no need (unless there actually is) to set those every time you hit the hotkey. Just specify them at the top of your script once.
Both of them are useless for you though, below I'll show why. Also DetectHiddenWindows is already off by default.
WinGetTitle is not good to use for this. What you actually want to do is get the hwnd of the window you wish by using e.g. WinExist().
And then refer to the window by its hwnd. Much better than working with window titles, and impossible to match the wrong window as well. To refer to a window by its hwnd, you specify ahk_id followed by the hwnd on a WinTitle parameter.
And lastly, the concatenation operator . is redundant. Of course you may prefer to use it, but in case you didn't know, it can just be left out.
Here's your revised code:
F10::
_HWND := WinExist("A")
MsgBox, % "Start hwnd = <" _HWND ">"
InputBox, mode, Test box, Testing,,260,160
Sleep, 500
WinActivate, % "ahk_id " _HWND
Return

Menu and submenu selection on specific app via Autohotkey

I have a dictionary application in which Ctrl+C does not work, so the only way to copy is to go from the menu, Edit > Copy. I have tried using the following code and variations of it, but it did not work.
!l::
WinActivate, MAGENTA - Dictionaries Explorer II
WinMenuSelectItem, ahk_class TMainForm,, Edit, Copy
return
WinSpy data:
MAGENTA - Dictionaries Explorer II
ahk_class TMainForm
ahk_exe MgDE2.EXE
ahk_pid 2580
Forgetting AHK for a minute, if you just press and release the Alt key (all by itself) what happens?
If the File menu activates (blue box), then you can just send the ALT keystroke followed by directional movement as needed and finally sending ENTER to activate the item
Like this
SendInput {Alt}{Right}{Down}{Enter}
If you needed to go right 4 elements and then down 2 entries you would use this way:
SendInput {Alt}{Right 4}{Down 2}{Enter}

Shortcuts key replacemento with AutoHotkey

I just started using Autohotkey (I am a noob with it) for remapping some key combinations like CTRL+TAB (which is good if you are using your left hand) to be accessible while using your right hand.
My initial script is the following:
RControl & RShift::
{
send {LControl down}{tab}{LControl up}
return
}
It works fine, but while switching tabs in Visual Studio, for example, I cannot hold the CTRL key to keep switching tabs, I can only switch between 2 tabs.
Does anyone know if it is possible to achieve this kind of functionality with Autohotkey?
Thanks in advance.
You don't need the { } around the hotkey body. Hotkeys simply start with :: and end with return. Braces are only needed in functions afaik.
send {LControl down}{tab}{LControl up} could be expressed easier by send ^{tab} which is Ctrl+Tab. The tab-switch in VS also works with right RCtrl.
In either way, this does not work because of the send {ctrl up}. Ctrl needs to stay pressed down in order for the "Active files" window to stay open. Try:
RControl & RShift::send {RCtrl down}{tab}