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

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.

Related

Send function key stroke from AutoHotkey to OBS Studio

I am trying to send a keystroke to OBS Studio using AutoHotkey.
The code I am using is
DetectHiddenWindows, On
hWnd := WinExist("ahk_exe obs64.exe")
ControlSend,, {F5}, ahk_id %hWnd%
The function I want to trigger is "start recording"
Nothing is delivered. There is a rumour that the latest OBS does not allow for ControlSend. Is that true? How do I circumvent that?
Use SetKeyDelay (or separate up & down events with delay in between) to make the key be held down for a bit longer.
;hold down for 50ms
SetKeyDelay, -1, 50
ControlSend, , {F5}, ahk_exe obs64.exe
Also, assuming you don't need the hwnd for something else, there's no need to get it.
And it should work just fine as well without detecting hidden windows.

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}

autohotkey to focus / open on google chromium

I have this autohotkey script that opens chrome if its not already on windows, and if it is, cycles through tabs within it. It also puts that chrome window on top of any other windows (e.g. excel docs, word docs, etc)
IfWinNotExist, ahk_class Chrome_WidgetWin_1
Run, chrome.exe
if WinActive("ahk_class Chrome_WidgetWin_1")
Send ^{tab}
else
WinActivate ahk_class Chrome_WidgetWin_1
Return
I can't seem to figure out how to get this to work for google chromium though. Both exe names are "chrome.exe", so I'm not sure what the run commands is if there's an overlap.
Also, I ran winSpy but still am not 100% sure what ahk_class name is. Below is the information from winSpy
I ended up settling for a different solution
After 2 days of tweaking and testing some workflows, this is what I settled with. I ran a combination of both phrase-express (any macro program works here) and autohotkey here, so I can have an extremely flexible layout
F1 → Binded to WIN+1 key
F2 → Binded to WIN+2 key
F3 → Binded to Win+4 key
F4 → Binded to Win+4 key
For F5 to F7 keys, I used autohotkey
F5::
IfWinNotExist, ahk_class Chrome_WidgetWin_1
Run, chrome.exe
GroupAdd, kjexplorers5, ahk_class Chrome_WidgetWin_1 ;You have to make a new group for each application, don't use the same one for all of them!
if WinActive("ahk_exe chrome.exe")
GroupActivate, kjexplorers5, r
else
WinActivate ahk_class Chrome_WidgetWin_1 ;you have to use WinActivatebottom if you didn't create a window group.
Return
F6::
IfWinNotExist, ahk_class ConsoleWindowClass
Run, cmd.exe
GroupAdd, kjexplorers6, ahk_class ConsoleWindowClass ;You have to make a new group for each application, don't use the same one for all of them!
if WinActive("ahk_exe cmd.exe")
GroupActivate, kjexplorers6, r
else
WinActivate ahk_class ConsoleWindowClass ;you have to use WinActivatebottom if you didn't create a window group.
Return
F7::
IfWinNotExist, ahk_class QWidget
Run, anki.exe
GroupAdd, kjexplorers7, ahk_class QWidget ;You have to make a new group for each application, don't use the same one for all of them!
if WinActive("ahk_exe anki.exe")
GroupActivate, kjexplorers7, r
else
WinActivate ahk_class QWidget ;you have to use WinActivatebottom if you didn't create a window group.
Return
F5 to F7 uses the same variant autohotkey, I just changed up the groupnames, the .exe files , and the ahk_class names.
This is how I organize the structure of my windows taskbar
So I press
F5 (3 times), and it pushes each chrome window I have up to the top of each of my 3 monitors.
F6 and I can quickly pop out whatever command prompts I have open, one command prompt for gulp commands, and one for git, independent of any IDE.
F7 twice to quickly add some new flashcards
I can restructure F1 F2 F3 F4 to whatever app I'm currently using. Anything that goes here I only keep one window per app at a time. Like I only run one firefox window (to watch tutorial youtube videos), only one running application of PHPstorm, etc.
Demonstration of F6 key in action (command prompt)

Creating a Mouse Hotkey

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).

How does this AHK script work?

The following AHK script automatically brings up the menu that you would normally get when you right-click on the uTorrent icon in the system task-bar tray:
DetectHiddenWindows, On
Process, Exist, utorrent.exe
WinGet, W, List, ahk_pid %ErrorLevel%
Loop %W%
{
WinGetClass, Class, % "ahk_id" W%A_Index%
If InStr( Class, "µTorrent" ) {
hWnd := W%A_Index%
Break
}}
PostMessage, 0x8001, 0,0x204,, ahk_id %hWnd% ; Right Click down
PostMessage, 0x8001, 0,0x205,, ahk_id %hWnd% ; Right Click Up
I understand most of it except the last two lines. 0x8001 is WM_APP+1. Why is a message in the WM_APP range used, and what exactly happens when these two messages are issued? Many thanks for the explanation.
According to MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/ms644927(v=vs.85).aspx#system_defined)
If your application is marked version 4.0, you can use message-identifier values in the range 0x8000 (WM_APP) through 0xBFFF for private messages.
So this would indicate that 0x8001 is an identifier that utorrent has chosen for a message. The 0x204 and 0x205 values are for the Right-Click Down and Up events respectively. My guess is that this code is intended to simulate a Right-Click on utorrent's icon in the Windows tray.
Also, if you're using Autohotkey_L the code can probably be simplified to three lines and perform the same:
DetectHiddenWindows, On
PostMessage, 0x8001, 0,0x204,, ahk_exe utorrent.exe ahk_class µTorrent ; Right Click down
PostMessage, 0x8001, 0,0x205,, ahk_exe utorrent.exe ahk_class µTorrent ; Right Click Up
When you right click on something, the context menu is shown. The context menu can also be shown by pressing the appskey button on the keyboard. When you press it, Windows sends the application a message, i.e., the WM_APP message. Most applications respond by showing a context menu. In the case of the tray icon, the response is the same as the response to a right-click.
Seems that the WM_APP+1 message number is a choice made in the development of the application, in this case utorrent. Could have been another message #, nothing magic. I believe the code I presented (which is from the AHK forums) figured out the message to send through reverse engineering.