AHK noob here. I'm looking to monitor 1-4 programs which run minimised for a specific change to the window title using autohotkey. When the change is detected in any of the programs, an alert pops up to alert the user of the change or the script could bring the program to the front.
The change in the window title (extracted using the AutoIt Spy tool) is from:
Lab - [Workspace... after this point the title text is dynamic
to either:
Lab - [Results ...etc
or simply
WARNING
The 4 programs are identical so as they're running out of separate folders stored as follows:
c:\program1\program.exe
c:\program2\program.exe
c:\program3\program.exe
c:\program4\program.exe
Could the PID be retrieved for each program so that the script can distinguish between the 4 and bring the correct one to the front? Any help from the community would be much appreciated.
Here is something, (not tested) to get you started...
SetTitleMatchMode, 1 ; A window's title must start with the specified WinTitle to be a match.
Settimer, CheckWindow, 1000
Return
CheckWindow:
Ifwinexists, ahk_class...... check the class first
{
IfWinExist, Lab - [Results
GoSub, MyAlert
IfWinExist, WARNING
GoSub, MyAlert
}
Return
MyAlert:
SoundBeep, 1000, 1000
Return
I see that you have expanded your question with the part discussing 4 similar .exe files. If you want to differentiate based on PID, you can use:
WinGet, active_id, ID, A ; A = active window...
WinMaximize, ahk_id %active_id%
MsgBox, The active window's ID is "%active_id%".
The fact that you ask this question is worrisome. one Google search AutoHotKey PID directs you to the answer. I am willing to help, but not your programmer!
Warning: If you edit your original question, we get no alert UNLESS you also write a new comment!
Related
I am new to AHK and would like to find the number of windows of a certain program open at any time and store that in a variable.
I have a script that opens an Opera window when I press the caps lock key, but I would only like three of these windows open at any one time, so when there are more than three Opera windows open and I press the caps lock key it does nothing.
I would also like the caps lock button never to capitalise text (in other words, to have caps lock state always off)
How do I do this?
You can use WinGet with the Count operation (see docs) to get the number of windows matching a certain filter.
You need to find the right filter of course. You can use the Window Spy utility for that which comes with AutoHotkey.
In this case I already did it: You'll see that the window class (ahk_class) of the Opera windows is Chrome_WidgetWin_1. However, this would be true for Chrome, Chromium, etc. as well, so we further have to filter for the program EXE filename (ahk_exe) of opera.exe. (The reason we don't just filter by ahk_exe is that we don't want to include things like an "there are updates available" box or whatever other non-main window Opera may have open, I guess.)
The final result is:
WinGet cnt, Count, ahk_exe opera.exe ahk_class Chrome_WidgetWin_1
MsgBox There are %cnt% Opera windows open
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
Even though I have read the docs and watched tutorials I am a complete beginner so I apologize If its a silly question. I have tried for quite a while to do this with no results.
I want to have NUMPAD0 key to press the global recording button in Ableton Live but I do not want to do it through mouse coordinates (1. Because the windows might be minimized when I need to record and 2. Because I want to implement this in the future in order to be able to press the recording button also on individual tracks as I create them, which might range from 1 to 80 new tracks for example)
The thing is that the Windows class dynamically changes and the Control ID is not shown in winspy.
This is what I have been doing:
GroupAdd, Live, ahk_class
Afx:0000000140000000:0:0000000000000000:0000000000900015:00000000007A04C3
GroupAdd, Live, ahk_class
Afx:0000000140000000:0:0000000000000000:0000000000900015:0000000000200651
GroupAdd, Live, ahk_class
Afx:0000000140000000:0:0000000000000000:0000000000900015:0000000000290651
GroupAdd, Live, ahk_class
Afx:0000000140000000:0:0000000000000000:0000000000900015:00000000001E05F1
curMode := 1
return
Numpad0::
SetControlDelay -1
controlclick, ahk_group Live0,,,,,NA
return
So, my issues are these: 1. In the GroupAdd command I have put the window classes that I have seen yet I believe there might be more classes, that appear everytime I open a new Ableton window. 2. In the Control Click command, I havent put the control ID because I couldnt find it.
Any advice on how to finish this code or change it to a different it in order to press that Record button in Ableton, without using coordinates?
EDIT:
This is the code Im trying now, following suggestions but I havent got any results yet:
SetTitleMatchMode, Regex
SetTitleMatchMode, Slow
#IfWinActive, .*als
Numpad0::F9
#IfWinActive
return
And this is the 2 version of that, which is not working either
SetTitleMatchMode, Regex
SetTitleMatchMode, Slow
#IfWinActive, Afx:0000000140000000
Numpad0::F9
#IfWinActive
return
While I've never used GroupAdd, if there's a finite number of Class permutations, it seems to me you could RegExMatch against those and then form your group inside that. The GroupAdd spec seems to make all parameters optional beyond the GroupName, so perhaps you could skip the Class declaration after confirming you've got the right window.
Example:
WinGetTitle, Title, A
WinGetClass, Class, A
if (RegExMatch(Title, "Ableton Live.*") AND (RegExMatch(Class, "(AbletonClass1|AbletonClass2|AbletonClass3)")))
{
; Do stuff
}
I am trying to make a hotkey that will copy a file in Windows Explorer, flip to my open new draft email and attach it. I am going to assume that there will be zero or one new draft email windows open. If there are more than one, I'll just take one and hope it's the right one. This is an interactive process. My trouble is in writing an IfWinExist that can tell the difference between an open sent email window and an open new draft email window. How can I tell the difference?
I'm using Outlook 2010 and AutoHotkey v1.1.12.00
Thanks for your help!
Here's a commented code example:
SetTitleMatchMode, 2
/* Choose the window title acoording to your language:
* English: Message
* German: Nachricht
* ...
*/
msgWin := "- Message ahk_exe outlook.exe"
WinGet, hwndList, List, %msgWin%
Loop % hwndList
{
aHwnd := hwndList%A_Index%
WinGetTitle, ttl, % "ahk_id " aHwnd
ControlGetText, btnText, Button1, ahk_id %aHwnd%
/* If you want to be sure, check for the text of the send button:
* English: &Send, German: &Senden, ...
*/
if(!btnText || !InStr(btnText, "Send")) {
MsgBox, Not a draft window:`n%ttl%
} else {
MsgBox, Draft window:`n%ttl%
}
}
It basically checks for each open Message window, if there's a Send button in it (for me, it's Button1). If there's no such button, it's not a draft.
As described in the code's comments, you'll have to adjust the language dependent identifiers. You may also have to change the control name (Button1), window spy will give you that info.
I have a window that displays a book. In two smaller boxes below, there is page number and volume information of the book that is open. I can get that information easily as follows:
ControlGetText, volume, ThunderRT6TextBox3
ControlGetText, page, ThunderRT6TextBox2
Then my script makes my mouse pointer move to a button. It clicks it, and a new window pops open. In that window, there is more textual information related to the book, such as publisher, name author, edition etc. I want to retrieve that information. But when I try the same strategy it is not working, eg:
ControlGetText, data, RichTextWndClass3
The only difference between the two cases, is that those two small boxes are editable, you can enter text whereas this window is static.
I tried many other options such as:
SendEvent ^a
Which is equivalent to control + a, which should select everything. I tried putting pauses but it would never select. I tried the script to manually double click on that window. It works, and one word gets select like that. Even then SendEvent ^a doesn't do anything.
However, if I do SendEvent ^{insert}, then the selected word gets copied to my clipboard.
I experimented with more combinations:
ControlSend ahk_class ThunderRT6FormDC, ^a
ControlSend ClassNN RichTextWndClass3, ^a
and
ControlSend ThunderRT6FormDC, ^a
ControlSend RichTextWndClass3, ^a
None of them work. All text selection does not manifest itself in that window.
The only alternative remaining for me is to make the script do a manual selection of the entire text. However, this is slow and very ridiculous. Moreover, in Window Spy under the section: Visible Window Text, the text is all there. I tried many other possibilities and I am at the end of my wits. How am I to harvest that text directly?
EDIT--
The text of the window shows in Window Spy under the heading: TitleMatchMode=slow Visible Text, NOT the heading: Visible Window Text
EDIT--
I spoke to you about two windows. The first one in which i get volume and page number. The second one which needs to pop up by pressing a button.
Both these windows have the same class-name:
ahk_class ThunderRT6MDIForm
Is that problematic in any way?
EDIT--
The conclusion is that it is impossible for me to get that text from the second window directly. As such, I opted for the lame, boring manual method. I send out a {shift down} to the active window and then do a click at the bottom of the window. Then I save the selection to my clipboard. It works, but it is just stupid. Please help me find a more elegant solution than this one.
This is the code I used:
ControlGetText, volume, ThunderRT6TextBox3
ControlGetText, page, ThunderRT6TextBox2
Click, 110, 70
sleep 1000
SendInput {shift down}
click 29, 490
SendInput {shift up}
sleep 1000
SendInput, ^{ins}
sleep 100
It is funny to note that real keyboard keys, such as a b c are not possible. But I am able to send a ctrl, shift and an ins. As I noted above, ^c was also giving issues just like ^a was giving issues.
This routine will do the job of getting and returning from the active window the following text sections:
- EdtWindowTextFastVisible
- EdtWindowTextSlowVisible
- EdtWindowTextFastHidden
- EdtWindowTextSlowHidden
MyGetWindowText(ByRef EdtWindowTextFastVisible, ByRef EdtWindowTextSlowVisible, ByRef EdtWindowTextFastHidden,ByRef EdtWindowTextSlowHidden)
{
; Source: https://code.google.com/p/autohotkey-cn/source/browse/trunk/Source/AHK_Window_Info/AHK_Window_Info_v1.7.ahk?r=6
EdtWindowTextFastVisible =
EdtWindowTextSlowVisible =
EdtWindowTextFastHidden =
EdtWindowTextSlowHidden =
WindowControlTextSize = 32767
VarSetCapacity(WindowControlText, WindowControlTextSize)
WinGet, WindowUniqueID, ID, A
;Suggested by Chris
WinGet, ListOfControlHandles, ControlListHwnd, ahk_id %WindowUniqueID% ; Requires v1.0.43.06+.
Loop, Parse, ListOfControlHandles, `n
{
text_is_fast := true
If not DllCall("GetWindowText", "uint", A_LoopField, "str", WindowControlText, "int", WindowControlTextSize)
{
text_is_fast := false
SendMessage, 0xD, WindowControlTextSize, &WindowControlText,, ahk_id %A_LoopField% ; 0xD is WM_GETTEXT
}
If (WindowControlText <> ""){
ControlGet, WindowControlStyle, Style,,, ahk_id %A_LoopField%
If (WindowControlStyle & 0x10000000)
{ ; Control is visible vs. hidden (WS_VISIBLE).
If text_is_fast
EdtWindowTextFastVisible = %EdtWindowTextFastVisible%%WindowControlText%`r`n
Else
EdtWindowTextSlowVisible = %EdtWindowTextSlowVisible%%WindowControlText%`r`n
} Else
{ ; Hidden text.
If text_is_fast
EdtWindowTextFastHidden = %EdtWindowTextFastHidden%%WindowControlText%`r`n
Else
EdtWindowTextSlowHidden = %EdtWindowTextSlowHidden%%WindowControlText%`r`n
}
}
}
;EdtWindowTextFastVisibleFull := ShowOnlyAPartInGui("EdtWindowTextFastVisible", EdtWindowTextFastVisible, 400)
;EdtWindowTextSlowVisibleFull := ShowOnlyAPartInGui("EdtWindowTextSlowVisible", EdtWindowTextSlowVisible, 400)
;EdtWindowTextFastHiddenFull := ShowOnlyAPartInGui("EdtWindowTextFastHidden", EdtWindowTextFastHidden, 400)
;EdtWindowTextSlowHiddenFull := ShowOnlyAPartInGui("EdtWindowTextSlowHidden", EdtWindowTextSlowHidden, 400)
Return
}
There is an autohotkey script that emulates most of the window spy logic. It is called AHK_Window_Info_v1.7.ahk. The nice thing is... you can run it to see if your second window text if visible to this script and if so... the logic needed to pull the information is available inside the script. Here is a link to the webpage and the script is available through SKANs dropbox link on that page. http://www.autohotkey.com/board/topic/8204-ahk-window-info-17/