Testing if a window is responsive - windows

I have this script to run a online game, click trough the startup screens and input my password for me.
Ever since the latest patch however, the %MWOStartupTime% has become rather unpredictable and this doesn't work reliably anymore. I'm suspecting the game is firing some early web requests. Or something.
So here's the question: Instead of waiting for a fixed time, can I somehow test if a given window not only exists but is responsive? That way I could loop, wait for a responsive window and start "clicking" then.
I'm also happy about alternative ideas/solutions. If it turns out I need to use the WinAPI I can rewrite it in a real programming language too.
Run, MWOClient.exe, %MWODirectory%
; Wait for the Client to launch
WinWait, MechWarrior Online,, 20
WinActivate, MechWarrior Online
; Wait until the window is responsive
Sleep, %MWOStartupTime%
; Press Escape a few times to skip the loading screens
Loop %MWOScreenLoops% {
WinActivate, MechWarrior Online
Sleep, %MWOScreenTime%
SendInput {Esc}
}
; Click the password textbox
WinActivate, MechWarrior Online
Click %MWOPasswordBoxXCoord%, %MWOPasswordBoxYCoord%
Sleep 500
; Type the password
WinActivate, MechWarrior Online
SendInput %MWOPassword%
Sleep 500
; Copy the password to the clipboard in case the
; password input fails
clipboard = %MWOPassword%
; Click login
Click %MWOPlayButtonXCoord%, %MWOPlayButtonYCoord%

Have you tried following WinActivate with WinWaitActive? You should be able to drop the Sleep command.
WinActivate, MechWarrior Online
WinWaitActive, MechWarrior Online
https://www.autohotkey.com/docs/commands/WinWaitActive.htm

Related

How to keep "new solution explorer views" after reload a project in Visual Studio 2015?

Every time I load my project I do organize my workspace into 3 "new solution explorer view". One Solution Explorer for the views folder, one for the models folder and the last one for the controllers folder.
However when I close and reopen my project it is set back to the default workspace. Is possible to keep those created solution explorer views ?
The Save workspace option don't work with multiples solutions explorers.
Unfortunately, the short answer is "you can't". I have been attempting to find a solution utilising the MS Macro addin, and some of the other tools available, but none of them seems to be able to automate the opening of additional solution views, let alone a way of persisting them once they are set up.
I was quite surprised that the "Save Window Layout" feature in VS2015 doesn't allow you to do this either. It simply ignores any additional solution views. My theory on this is that, as the views are solution specific, it doesn't make sense to have them persisted as a default for the entire environment.
Here is a rather dirty solution I came up with in the last hour. It uses an AutoHotKey script which does what you would do by hand. The case in the code is quite specific, since I want to open two panes on top of each other each one searching for a specific search term, but you can easily modify the code to suit your needs.
What I want to end up with
Usage
Have the solution Explorer on Docked Mode and on "Show all Files" view. Double click the script, which should have the ending .ahk with AutoHotKey installed. You have 2 seconds to Alt+Tab to Visual Studio, where the script will do it's thing. When it is done, close the original Solution Explorer by hand.
The Script
FolderPos = 2 ; Position of Target Folder, Example in the picture below
XPosFirst = 24 ; How many times to press right
YPosFirst = 42 ; How many times to press down
SearchTermFirst = "cpp" ; Text to search in the explorer
XPosSecond = 22
YPosSecond = 13
SearchTermSecond = "hpp"
InitiateMove() {
Send !{Space}
Send M
}
NewSolutionExplorer() {
Send {AppsKey}
Send N
}
ExitSearch() {
Send {Down}
Send {Up 5}
Send {Down}
}
BlockInput MouseMove
Sleep 2000
SetKeyDelay 10
Send ^!l
Send {Down %FolderPos%}
NewSolutionExplorer()
SetKeyDelay 80
InitiateMove()
Send {Right %XPosFirst%}
Send {Down %YPosFirst%}
SetKeyDelay 10
Send {Enter}
Send ^;
Send %SearchTermFirst%
ExitSearch()
NewSolutionExplorer()
SetKeyDelay 80
InitiateMove()
Send {Right %XPosSecond%}
Send {Down %YPosSecond%}
SetKeyDelay 10
Send {Enter}
Send ^;
Send %SearchTermSecond%
ExitSearch()
BlockInput MouseMoveOff
ExitApp
FolderPos Example: Folder src is on position 2
For VS2017 and VS2019 I found extension 'Multiple Solution Explorer Tools'. Only problem - it does not maintain view windows position and size after load.

How to close/minimize/maximize or send keys to window or popup with Autohotkey?

How to use Autohotkey to automatically close, minimize, maximize or send keys to a window as soon as it pops up? I can detect a dialog and close it with this:
WinWaitActive, TITLE
WinClose, TITLE
But this doesn't work if the window isn't open on script execution.
This is a very common task AHK is used for.
First you need the title of the window you want to address. Read How to get the title of a window with AHK?.
The code
For the basic functionalitiy of closing a window we need Loop, WinWaitActive and WinClose.
Example for a Firefox window with Stack Overflow open.
Loop {
WinWaitActive, Stack Overflow - Mozilla Firefox
WinClose,
}
Explanation
The Loop repeats the process to close the window multiple times. WinWaitActive waits until the the window gets activated (pops up) and WinClose closes it.
Hint: If you don't specify a specifiy window title like with WindowClose the last found window, which is the one from WinWaitActive is used.
minimize/maximize
Instead of WinClose use WinMaximize or WinMinimize to perform the corresponding action.
Sending Keys
If you want to send specific keys (e.g. Enter) to the window use Send
Loop {
WinWaitActive, Stack Overflow - Mozilla Firefox
send {Enter}
}
Additions
If the basic version does not work or you want to create an more advanced script, here are some possible modifications.
More Force
If WinClose does not work try WinKill or Send, !{F4} to use more force.
As Admin
Admin rights might be necessary to close the window, use this code snippet on top of your script to make sure it runs with full access.
If not A_IsAdmin ;force the script to run as admin
{
Run *RunAs "%A_ScriptFullPath%"
ExitApp
}
Other matching methods
On default the window title has to be an exact match. To change this behavior and allow partial or start with matches use SetTitleMatchMode on top of your script, e.g. SetTitlematchMode, 2 for partial match.
Instead of title, the window class (ahk_class) or .exe (ahk_exe) from Window Spy can be used.
WinWaitActive, ahk_class MozillaWindowClass
or
WinWaitActive, ahk_exe firefox.exe
Select the one which suits your needs carefully to only react to the correct window.

How to execute an autohotkey script when launching a specific application

I have successfully used to following autohotkey script to achieve what I want (remove title bar and window frame from a windowed game):
;-Caption
LWIN & LButton::
WinSet, Style, -0xC00000, A
return
;
;+Caption
LWIN & RButton::
WinSet, Style, +0xC00000, A
return
;
What I want is for "WinSet, Style, -0xC00000, A" to be executed automatically when a specific application is launched.
Any feedback would be greatly appreciated!
Altough wOxxOm's answer is perfectly acceptable. You can also do this in a persistent script by using Settimer and WinExist .
#persistent
SetTimer, isItRunning, 1000
isItRunning:
if winexist("yourprogram")
WinSet, Style, -0xC00000
Return
Simply make an AHK launcher for the game and use it instead of the shortcut icon or taskbar icon or whatever else you're using to launch the game.
Run, d:\somepath\game.exe
WinWait Game window title goes here
WinSet, Style, -0xC00000
ExitApp

AutoHotKey - "Continue" and "Cancel" Buttons

I am a newbie with AutoHotKey, and to this point I consider myself fortunate to have created a script to automate about 90% of the data entry in a window. I'm now trying to kick it up a notch and add a warning/caution GUI to my data entry script. I want to pause the running script and open a GUI that will alert me to look at what has already been entered, with one button to allow things to proceed if a particular entry looks OK, and another to dump out of both the GUI and the remainder of the script if the entry is incorrect.
Here's some code I came up with, mixed with some pseudocode to help show what I want to do.
(Previous data entry script executes to this point)
Stop the script
Gui, New
Gui, Add, Text, 'n Check Authorization Number to be sure it is A1234 (FY 15). ; Wraps text
Gui, Add, Button, Default, Continue
Gui, Add, Button, Quit
Gui, Show, IMPORTANT!
If Continue button is clicked
----Continue with script
If Abort button is clicked
----Close the GUI
----Exit the entire script
(Resume where I left off with rest of the data entry script)
I've read the AHK Help file and am stumped about how to make these buttons work, as well as how to properly return from the GUI back to the script if I hit continue, or quit the whole thing if I spot a problem. I can tweak things like the size of the GUI and the button placement; what's most important is getting the GUI code right. Can someone help with the code? (The last programming class I took was in 2003, so I have forgotten a whole lot!)
In your case, a GUI would be overkill. AHK (and many other languages at that) provide standard dialogs for simple user interaction called message boxes.
Message boxes in AHK can be displayed in two ways:
MsgBox, This is a simple message. Please click "OK".
MsgBox, 4, Attention, Here`, you can choose between "Yes" and "No".
In the second case, we declared an option which controls the buttons that are displayed. You can use IfMsgBox in order to detect what the user has clicked:
IfMsgBox, Yes
MsgBox, 4, Really?, Did you really mean "Yes"?
Putting these pieces together, we can ask the user to decide if they want to continue, without the need to create a GUI, in a few lines:
; Option "1" is "OK/Cancel"
MsgBox, 1, IMPORTANT!, Check Authorization Number to be sure it is A1234 (FY 15).
IfMsgBox, Cancel
{
ExitApp
}
; do stuff
This code addresses each of your other problems, too:
A message box halts the current thread until the user dismisses the dialog or it times out (if you specifically declared a timeout).
To completely stop the execution of our script, we use ExitApp.

capturing right-click+left-click with autohotkey; unexpected behaviour

I want to capture the key event "right mouse button pressed, then left mouse button pressed". No problem in autohotkey. However I am having trouble with still allowing the right-mouse key to work alone.
1) this works:
RButton & LButton::
Send X
Return
works as expected:
If I press right mouse button, then left mouse button, "X" is sent to the active window
right-click event is captured by Authotkey: no context menu appears when I press the right mouse button alone. This is the intended outcome
2) this works
~RButton & LButton::
Send Y
Return
works as expected:
If I press right mouse button, then left mouse button, "Y" is sent to the active window
right-click event is not captured by Authotkey: context menu does appear when I press the right mouse button alone or together with the left button. This is the intended outcome
3) Now I want to do different things depending on the active window.
this does not work (careful: this will disable righ-click in every application)
#If WinActive("ahk_class MozillaWindowClass")
RButton & LButton::
Send X
Return
#If !WinActive("ahk_class MozillaWindowClass")
~RButton & LButton::
Send Y
Return
does not work as expected:
in Firefox left-right sends X, in other applications left-right sends Y
however, right-click is disabled in every application
What am I doing wrong here?
edit:
the goal is this: I want a global hotkey on Right+left-click with RButton & LButton . In specific applications that I have tested for compatibility, I want right+left click to suppress sending right-click, and then send right-click manually using autohotkey. However, since some applications might have trouble processing mouseevents sent by autohotkey, in all untested applications I want to use ~RButton & LButton with the ~ to pass throught right-click events
Here's one that supports right click dragging!
Hotkey, LButton, off
#IfWinActive ahk_class MozillaWindowClass
RButton & LButton::
Send X
Return
RButton::return
#IfWinNotActive ahk_class MozillaWindowClass
~$RButton::
Hotkey, LButton, on
while GetKeyState("RButton", "P") {
continue
}
Hotkey, LButton, off
Return
LButton::Send Y
Return
It handles RButton manually. When RButton is pressed, it enables the LButton hotkey and waits for RButton to be released before deactivating it. The RButton hotkey uses ~, which passes the click through normally.
LButton is disabled at the start by the line at the top.
Another way would have been to send {RButton Down} at the start of the hotkey and {RButton Up} at the end.
In response to your edit, the only programs that reject Autohotkey's sent events should be those that rely on low level hooks... The real trouble with the method down at the bottom is it only sends a single click, not processing holding the button. This method, and sending down and up separately, should both do that properly.
The bug with active window described at the bottom of this answer still exists, but that's a problem with the #IfWin[Not]Active.
Old stuff
See the documentation on the ampersand (emphasis mine):
You can define a custom combination of two keys (except joystick buttons) by using " & " between them. In the below example, you would hold down Numpad0 then press the second key to trigger the hotkey:
Numpad0 & Numpad1::MsgBox You pressed Numpad1 while holding down Numpad0.
Numpad0 & Numpad2::Run Notepad
In the above example, Numpad0 becomes a prefix key; but this also causes Numpad0 to lose its original/native function when it is pressed by itself. To avoid this, a script may configure Numpad0 to perform a new action such as one of the following:
Numpad0::WinMaximize A ; Maximize the active/foreground window.
Numpad0::Send {Numpad0} ; Make the release of Numpad0 produce a Numpad0 keystroke. See comment below.
The presence of one of the above hotkeys causes the release of Numpad0 to perform the indicated action, but only if you did not press any other keys while Numpad0 was being held down.
So, following that example:
#If WinActive("ahk_class MozillaWindowClass")
RButton & LButton::
Send X
Return
RButton::return
#If !WinActive("ahk_class MozillaWindowClass")
RButton & LButton::
Send Y
Return
RButton::Send {RButton}
Note RButton requires a variant that does nothing in WinActive, at least with my testing (see below): RButton::return
Since I'm using Autohotkey standard, not Autohotkey_L, I don't have #If and the above was untested. The following I did test, and it works.
#IfWinActive ahk_class MozillaWindowClass
RButton & LButton::
Send X
Return
RButton::return
#IfWinNotActive ahk_class MozillaWindowClass
RButton & LButton::
Send Y
Return
RButton::Send {RButton}
An interesting bug I've noticed is the second (NotActive) variant applies occasionally to Firefox:
Another window is active
RButton down is sent
Firefox is not active, so the second variant is processed
<delay> (RButton is held down, though the delay could be imperceptible, in the order of milliseconds, to infinite)
Firefox becomes active
<delay> (still held down)
RButton up is sent, which sends RButton as per the documentation. Because Firefox became active in the delay between the active window check and when RButton is sent, RButton is sent to Firefox.
This happens when both Firefox and another window are visible, and the other window is the active one at the time of the click.
I've tried to fix this bug by adding an extra IfWinNotActive check within the RButton hotkey, but it did not seem to work.

Resources