How to simulate key press on a background window - autohotkey

I need to force Outlook which is in the background, to check for new emails every 2 seconds. So I wrote a following script but it doesn't do it. What's wrong? I don't want the script to disturb what I do and give the focus to the Outlook window. The "ahk_class rctrl_renwnd32" is correct, I checked it with "WinActivate, ahk_class rctrl_renwnd32" and it worked.
Loop
{
ControlSend,, {F9}, ahk_class rctrl_renwnd32
Sleep 2000 ; Wait 2 seconds
}

There is no error in your code. The problem might be in the receiving application. When I test this in Notepad, an F5 (Print time & date) is executed when the Notepad window is open somewhere on my second screen. As soon as I minimize Notepad, it will no longer execute F5, but it still accepts a string like A{Enter}B{Enter}C{Enter} when minimized.
!q::
ControlSend,, {F5}A{Enter}B{Enter}C{Enter}, ahk_class Notepad
Return
Solution, Try if this works when you keep the window on screen somewhere (no need to have the focus).
I have used Outlook in the past and remember that F9 took some time to execute. Running this every 2 seconds looks like overkill.
If getting your e-mail in time is THAT important that you are willing to "kill" the mail server with refresh requests, I would discuss a solution with your IT support.

Related

How can I open the URL in my script in a background tab?

So I have this code:
f9::
Send, ^c
Run, msedge.exe http://www.google.com/search?q="%clipboard%"
return
And I want to make a version of this script where the URL is opend in a background tab.
Perhaps look at the Help for Run as follows: https://www.autohotkey.com/docs/commands/Run.htm
FROM THE HELP (this is not the code, but only explanation):
Syntax: Run, Target , WorkingDir, Options, OutputVarPID
Parameters: Options
Min: launch minimized or Hide: launch hidden
So your code (that one line anyway) would be:
Run, msedge.exe http://www.google.com/search?q="%clipboard%", , Min
And that should do it! But if it doesn't (some windows don't respond to those options) then just wait a bit and minimize the window as follows:
Run, msedge.exe http://www.google.com/search?q="%clipboard%", , Hide
Sleep, 3000 ; timing in ms so 3 seconds is probably more than you need
WinMinimize, %clipboard% ; since the window title will include it
Enjoy,

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

AutoHotKey WinActive returns wrong value when changing window focus

In my AutoHotKey script I'm using #IfWinActive to detect if the Roblox window is in focus, and then press the number 1 button whenever left clicking the mouse, like this:
#IfWinActive, Roblox
LButton::
MouseClick, Left
SendInput, {1}
return
#IfWinActive
It works great, except for when I'm clicking out of the Roblox window back to another window. It still fires this code on the first click, resulting in it typing the number 1 into Notepad (or whatever window I switch focus to).
I figured that when I'm clicking on Notepad the focus is still on the Roblox window, which is why the code still fires. So I tried changing the code to this:
#IfWinActive, Roblox
LButton::
Sleep, 100
if WinActive("Roblox")
{
MouseClick, Left
SendInput, {1}
}
return
#IfWinActive
Assuming that by the time the Sleep finished the focus would have shifted to the Notepad window and If WinActive("Roblox") would return false, but it still returns true and types 1 into Notepad.
I also tried using StartTimer and a label, thinking that maybe the Sleep wasn't asynchronous, but that has the same problem as well.
Anybody know how to get around this issue? Thanks in advance!
The main problem in this case is that the hotkey is fired immediately after LButton is pressed down and the Roblox window is still active.
The only solution I see is to fire the hotkey upon release of the LButton using the tilde prefix (~) to prevent AHK from blocking the key-down/up events:
#IfWinActive, Roblox
~LButton Up:: SendInput, 1
#IfWinActive
There are a couple of ways we can achieve this. TL;DR for solution, check the yellow part of this post.
Firstly I'll address the problems in your code:
Usage of MouseClick over Click. Technically nothing wrong, but Click is said to be more reliable in some situations and easier to use. Looks cleaner as well.
Wrapping 1 in {} is not needed and does nothing for you here. In some cases you may even produce unwanted behavior by doing this. In a send command, {} is used to escape keys that have special meaning, or to define keys that you can't just type in. More about this from the documentation.
Having a somewhat of a bad WinTitle that you're matching against. Again, nothing technically wrong, but right now you match any window that starts with the word Roblox. Shouldn't be too hard accidentally match the wrong window.
A quick and a very effective solution would be matching against the process name of your Roblox window.
So #IfWinActive, ahk_exe Roblox.exe or in an if-statement if (WinActive("ahk_exe Roblox.exe")) (assuming that's the process' name, I have no idea)
For an absolutely fool proof way could match against the hwnd of the Roblox window. However, that's maybe a bit overkill and you couldn't really use it with #IfWinActive either. An example I'll write below will use this that though.
However, problems 1 and 2 can be entirely avoided by doing this neat way of remapping a key (remapping is pretty much what you're doing here).
~LButton::1
Ok, so why does that work?
key::key is just the syntax to easily do a basic remap, and with ~ we specify that the hotkey isn't consumed when it fires.
Cool, but now onto the actual problem you're having.
So what went wrong with the sleeping thing? Well since you're consuming the hotkey, all you're actually doing is firing the hotkey, waiting 100ms, then checking if Roblox is active. Well yes, it will still be active since nothing was ever done to switch focus away from it.
If you were to not consume the left clicking action, it would work, but it's definitely not a good idea. You do not want to sleep inside a hotkey statement. AHK does not have true multithreading and unless you would've specified a higher #MaxThreadsPerHotkey for your hotkey, all subsequent presses of the hotkey would be totally ignored for that 100ms.
So yes, with specifying a higher amount of threads that can run for that hotkey, it would kind of make this solution work, but it's still bad practice. We can come up with something better.
With timers you can avoid sleeping in the hotkey statement. Sounds like you tried the timers already, but I can't be sure it went right since code wasn't provided so I'll go over it:
#IfWinActive, ahk_exe Roblox.exe
~LButton::SetTimer, OurTimersCallbackLabel, -100 ;-100 specifies that it runs ONCE after 100ms has passed
#IfWinActive
OurTimersCallbackLabel:
if (WinActive("ahk_exe Roblox.exe"))
SendInput, 1
return
And now onto the real solution, to which #user3419297 seems to have beat me to, just as I'm writing this line of text.
Using the up event of your LButton press as the hotkey.
#IfWinActive, ahk_exe Roblox.exe
~LButton Up::SendInput, 1
#IfWinActive
This way the down event has already switched focus of the window and our hotkey wont even fire.
Note that here we unfortunately can't use the key::key way of remapping I described above.
Bonus:
Here's something that could be used if the up event of our keypress wouldn't be desirable, or somehow the window switching of the active window was delayed.
RobloxHwnd := WinExist("ahk_exe Roblox.exe")
#If, RobloxUnderMouse()
~LButton::1
#If
RobloxUnderMouse()
{
global RobloxHwnd ;specify that we're using the variable defined outside of this function scope
;could've also ran the code to get Roblox's hwnd here every time, but that would be wasteful
MouseGetPos, , , HwndUnderMouse ;we don't need the first two parameters
return RobloxHwnd == HwndUnderMouse ;are they the same hwnd? (return true or false)
}
Here we're first storing the hwnd of our Roblox to the variable RobloxHwnd.
Note that Roblox would need to be running before we run this script, and if you restart robox, script would need to be restarted as well.
So adding some way of updating the value of this variable on the fly would be good, maybe under some hotkey.
Then by using #If we're evaluating an expression (in our case, running a function and evaluating its return value) every time we're about to attempt to fire the hotkey. If the expression evaluates to true, we fire the hotkey.
Usage of #If is actually not recommended, and it is good practice to avoid using if at all possible. However, you wont encounter any problems in a script this small, so using #If is going to be very convenient here.
If you were to have a bigger script in which there's a lot of code running often, you'd be likely to run into problems.

Auto Hot Key: Strange behavior on ControlClick after Gui Submit

I have the following script that sends ControlClick + ControlSend to a window in background (while I'm working in another window). It works ok as expected.
SetTitleMatchMode 2
$F1::
sleep 1000
ControlClick, x400 y470, Notepad
ControlSend,, text, Notepad
return
The problem is: when I add a Gui on the script, the ControlClick behavior becomes odd once I close the Gui (with Submit or Destroy): If I'm working in a window A (Chrome for example) the ControlClick don't work in background anymore: it activates the window B (Notepad) like in the WinActivate command instead.
Here's the script with the issue (same as the previous one but with a simple Gui):
SetTitleMatchMode 2
Gui, Add, Text,, box
Gui, Add, Button, default, OK
Gui, Show, W300 H300
return
GuiClose:
ButtonOK:
Gui, Submit
return
$F1::
sleep 1000
ControlClick, x400 y470, Notepad
ControlSend,, text, Notepad
return
I'm on Windows Vista 32 bits, Autohotkey v1.1.25.01
I can't understand why the Gui Submit is changing the ControlClick bahavior. How can I fix this and let the ControlClick run in background just like it was without the Gui Submit/Destroy?
ps: both windows were maximized.
ControlClick is known to not be very reliable in certain cases. Take a look at the Reliability section in the ControlClick documentation, there are some things you can try:
To improve reliability -- especially during times when the user is
physically moving the mouse during the ControlClick -- one or both of
the following may help:
Use SetControlDelay -1 prior to ControlClick. This avoids holding
the mouse button down during the click, which in turn reduces
interference from the user's physical movement of the mouse.
Specify the string NA anywhere in the sixth parameter (Options) as
shown below:
SetControlDelay -1
ControlClick, Toolbar321, WinTitle,,,, NA
NA avoids marking the target window as active and avoids
merging its input processing with that of the script, which may
prevent physical movement of the mouse from interfering (but usually
only when the target window is not active). However, this method might
not work for all types of windows and controls.

traytip when window becomes active?

I want to simply display a tooltip when a window becomes active.
Why doesn't this work? It launches the tooltip as soon as the script is loaded.
#IfWinActive, Untitled - Notepad
{
TrayTip, Notepad Has Focus, test
Tab::
MsgBox Window Found
return
}
Tab detection works as expected, it shows the Message Box only if the window is active.
As per the #If... docs, #IfWinActive creates context-sensitive hotkeys and hotstrings. To be a bit more precise, this is what happens when you use #IfWin...:
Whenever you press a hotkey or type a hotstring, AHK looks up the corresponding #IfWin... definition (if available) and evaluates it (e.g. "Is notepad active?"). If it is true, the hotkey/hotstring label will be executed, otherwise the native key will be sent.
Looking at this procedure, you will recognize that executing arbitrary code below a #IfWin... statement won't work; AHK doesn't fire an event when a specified window becomes active/existent etc, it rather checks the conditions when a corresponding hotkey/hotstring is fired.
Ergo, you will have to write code that waits for notepad, shows a notification and possibly repeats this procedure:
#Persistent
SetTimer, WaitForNotepad, -1
Exit
WaitForNotepad:
WinWaitActive, ahk_class Notepad
TrayTip, Warning, Notepad is active!
WinWaitNotActive
SetTimer, WaitForNotepad, -1
return
Please note that this would also work without SetTimer in some kind of loop. But whenever you're waiting a potentially large amount of time, it is reasonable to use timers, since they virtually allow other threads to run in between.
You also noticed that I used the window class (ahk_class) instead of the window title, since it's usually more reliable.