Why my Auto hot key script doesn't work properly? - autohotkey

I use AutoHotkey for windows. I want to write a script in order to paste (the text I copied earlier) with middle button click of the mouse to searchbar of the program Oxford dictionary on my computer. and also when the the window of the program is closed, after I clicked middle button of the mouse automatically open the window and do the same thing I wanted( paste the copied word into the searchbar of program). I write this code :
MButton::
IfWinExist, Oxford Advanced Learner's Dictionary
{
WinActivate
Click, 182, 133, 2
Send, ^a{Delete}
sleep, 100
Send, ^v{Enter}
}
else
{
Run, "E:\dictionary oxford\OALD9.exe"
WinActivate, Oxford Advanced Learner's Dictionary
sleep, 500
Click, 182, 133, 2
Send, ^a{Delete}
sleep, 100
Send, ^v{Enter}
}
return
When I run the code, it just do the first task I wanted. It paste into the search bar of the Oxford Dictionary when it is open. But when it is closed, after I click middle button of the mouse it just open the program and doesn't paste the word into the searchbar.

WinWait is your friend.
Documentation
MButton::
IfWinExist, Oxford Advanced Learner's Dictionary
{
WinActivate
Click, 182, 133, 2
Send, ^a{Delete}
Sleep, 100
Send, ^v{Enter}
}
else
{
Run, "E:\dictionary oxford\OALD9.exe"
WinWait, Oxford Advanced Learner's Dictionary,,4
WinActivate, Oxford Advanced Learner's Dictionary
Sleep, 500
Click, 182, 133, 2
Send, ^a{Delete}
Sleep, 100
Send, ^v{Enter}
}
return
Edit: You might want to consider RunWait, also. Documentation

Related

Auto Hot Key - can't interrupt a loop

Here is an example auto hot key script:
^j::
WinActivate, MyWindow
WinWaitActive, MyWindow
Loop
{
If GetKeyState("Shift", "P")
Break
Click, 44, 55
Sleep, 1000
Click, 144, 155
Sleep, 1000
}
return
Everything works fine but I can't interrupt the loop by pressig "Shift". What is wrong ?
You have to hold the Shift key for more than 2 seconds pressed, because of the sleep times.
Or try something like this:
^j::
Loop
{
If !WinActive("MyWindow")
{
WinActivate, MyWindow
WinWaitActive, MyWindow
}
Click, 44, 55
Sleep_1000()
Click, 144, 155
Sleep_1000()
}
return
Sleep_1000(){
Loop 10
{
Sleep, 100
If GetKeyState("Shift", "P")
exit ; terminate the hotkey's thread
}
}
Using a loop inside a hotkey definition is bad practice.
AHK doesn't provide true multithreading, so long running loops are generally a really bad idea.
Using a timer fixes this, and usage of a timer is anyway always what you want for something like this.
And it'll be much more simple as well.
So, with Ctrl+j we activate the desired window and create the timer and tell it to run our function TimerCallback (which we will shortly create) every 2secs:
^j::
WinActivate, MyWindow
WinWaitActive, MyWindow ;shouldn't be needed, but if you find it helpful, fair enough
TimerCallback() ;run the function once, since the timer is going to
;run it for the first time only after 2secs
SetTimer, TimerCallback, 2000
return
And then we make shift be a hotkey for turning off the timer. And we for sure want to use the ~ modifier to not consume the key when the hotkey is fired:
~Shift::SetTimer, koira, Off
And now lets also define our function TimerCallback:
TimerCallback()
{
Click, 44, 55
Sleep, 1000
Click, 144, 155
}
So here's again the script in full if something was somehow left unclear:
^j::
WinActivate, MyWindow
WinWaitActive, MyWindow ;shouldn't be needed, but if you find it helpful, fair enough
TimerCallback() ;run the function once, since the timer is going to
;run it for the first time only after 2secs
SetTimer, TimerCallback, 2000
return
~Shift::SetTimer, TimerCallback, Off
TimerCallback()
{
Click, 44, 55
Sleep, 1000
Click, 144, 155
}

open program from windows Tray

I made a script that simply opens or activate specific app.
it works great but I have one issue, when the app minimized to windows tray.
the Hotkey activate the Else statement part so it creates another instance of the same app.
!a::
If WinExist("ahk_exe Orzeszek Timer.exe")
{
WinActivate, ahk_exe Orzeszek Timer.exe
}
Else {
Run, "D:\Portable\PortableApps\Orzeszek Timer\Orzeszek Timer.exe"
}
Return
I need help with script to trigger the IF statement part in case the app appears in system tray.
Much Thanks in advance)
Try this
!a::
Process, Exist, Orzeszek Timer.exe
If (Errorlevel != 0) ; is running
{
WinGet, WinState, MinMax, ahk_exe Orzeszek Timer.exe
If (WinState = "") ; is minimized to tray
SendInput, #bo{Enter} ; Win+b activates the tray, o marks the icon of Orzeszek Timer
else
WinActivate, ahk_exe Orzeszek Timer.exe
}
else ; is NOT running
Run, "D:\Portable\PortableApps\Orzeszek Timer\Orzeszek Timer.exe"
return
If the program has its own hotkey to restore the window, use that hotkey instead of #bo{Enter}.
EDIT:
If SendInput, #bo{Enter} is too fast to restore the program, add a sleep between the keys to send:
...
If (WinState = "") ; is minimized to tray
{
SendInput, #b ; Win+b activates the tray
; WinWaitActive, ahk_class Shell_TrayWnd
Sleep, 300
SendInput, o ; o marks the icon of Orzeszek Timer. Try first of all manually which letter marks the icon
Sleep, 300
SendInput, {Enter}
}
...
EDIT 2:
I downloaded that small portable app and this is working on my system:
!a::
Process, Exist, Orzeszek Timer.exe
If (Errorlevel != 0) ; is running
{
WinGet, WinState, MinMax, ahk_exe Orzeszek Timer.exe
If (WinState = "") ; is minimized to tray
; SendInput, #bot{Enter} ; OR:
SendInput, #b{Enter}{Up}ot{Enter}
}
else ; is NOT running
Run, "D:\Portable\PortableApps\Orzeszek Timer\Orzeszek Timer.exe"
WinWait, Orzeszek Timer,, 10
If (!ErrorLevel)
{
WinActivate, Orzeszek Timer
WinWaitActive Orzeszek Timer,, 5
If (!ErrorLevel)
MouseMove, 150, 80, 0
}
return
EDIT 3:
If you don't have the option "Always show all icons in the notification area" in the Settings enabled, try replacing
SendInput, #bot{Enter}
with
SendInput, #b{Enter}{Up}ot{Enter}
user3419297 much thanks for your script it works great. I Modified it a little to be open the app.
!a::
Process, Exist, Orzeszek Timer.exe
If (Errorlevel != 0) ; is running
{
WinGet, WinState, MinMax, ahk_exe Orzeszek Timer.exe
If (WinState = "") {
SendInput, #bo{Right}{Enter}
Sleep, 500
CoordMode, Mouse, Window
MouseMove, 150, 80, 0
}
else
WinActivate, ahk_exe Orzeszek Timer.exe
}
else ; is NOT running
Run, "D:\Portable\PortableApps\Orzeszek Timer\Orzeszek Timer.exe"
return
only one minor disadvantage the script depend on app been place first
in windows tray list.
of course I could always redefine {Right x} placement but is there more efficient way to find automatically app placement in tray?
finally works! the only missing part in script was {Up} key as pointed on edit 3 for system tray to become searchable. so now I had no problem to find the exact key. in my case it was
SendInput, #b{Enter}{Up}tt
Sleep, 100
SendInput, {Enter}
I Really don't know how to thank you. you helped me alot )

AutoHotKey - Looping through file dosen't stop after file ends, Send not sending variable

So this is my very first AHK program and I am not at all familiar with the language. I am familiar with C# though. I have the following `program that loops trough a file and splits a username and password split by a pipe (|) symbol. Right now when I run the program, it does not stop looping after the end of the file.
In addition, I try to access the username and password separated by the pipe symbol using the StrSplit function. so far, when I run the program, the username is only sometimes enteredcorrectly into the browser. The password is not entered into the browser. I am pretty sure `I am using the right mouse coordinates.
Thanks in advance` for the help!
#SingleInstance, Force
SetWorkingDir, %A_ScriptDir% ; if an absolute path isn't specified
;; GUI input
;-------------------------------
; ---------------------------------------
Gui, Add, Button, x10 y20 gStart, Start the tool
Gui, Show, w300 h300, Steam Tool
return
; Labels
; -----------------------
; --------------------------------
Start:
Loop, read, accounts.txt ; the file name must be separated by a comma
{
; MsgBox %A_LoopReadLine%
loop, parse, A_LoopReadLine,
{
IfWinNotExist, Multiloginapp - 01.3.15
{
Run, C:\Program Files (x86)\Multiloginapp\multiloginapp.exe
WinWait, Multiloginapp - 01.3.15
Sleep, 20000
}
IfWinNotActive, Multiloginapp - 01.3.15, ,WinActivate, Multiloginapp - 01.3.15
WinWaitActive, Multiloginapp - 01.3.15
Click 724, 260
sleep, 1500
WinWait, Multiloginapp - Mozilla Firefox
WinActivate, Multiloginapp - Mozilla Firefox
WinWaitActive, Multiloginapp - Mozilla Firefox
Click 408, 55
Sleep 5000
Send, ^a
Send, {Backspace}
SendInput, store.steampowered.com/account ; SendInput is faster in sending text
Send, {enter}
Sleep, 5000
; Use:
; SendInput, %A_LoopField%
; if you want to send the current substring (field) from the line
s:=StrSplit(A_LoopReadLine, "|")
Click, 149, 355
urnme := s[0]
Send, %usrnme%
Click, 172 455
pwd := s[1]
Send, %pwd%
Click, 87 507
}
}
return
Try it this way:
#SingleInstance, Force
SetWorkingDir, %A_ScriptDir% ; if an absolute path isn't specified
;; GUI input
;-------------------------------
; ---------------------------------------
Gui, Add, Button, x10 y20 gStart, Start the tool
Gui, Show, w300 h300, Steam Tool
return
; Labels
; -----------------------
; --------------------------------
Start:
IfWinNotExist, Multiloginapp - 01.3.15
{
Run, C:\Program Files (x86)\Multiloginapp\multiloginapp.exe
WinWait, Multiloginapp - 01.3.15
Sleep, 20000
}
IfWinNotActive, Multiloginapp - 01.3.15, ,WinActivate, Multiloginapp - 01.3.15
WinWaitActive, Multiloginapp - 01.3.15
Click 724, 260
sleep, 1500
WinWait, Multiloginapp - Mozilla Firefox
WinActivate, Multiloginapp - Mozilla Firefox
WinWaitActive, Multiloginapp - Mozilla Firefox
Click 408, 55
Sleep 5000
Send, ^a
Send, {Backspace}
SendInput, store.steampowered.com/account ; SendInput is faster in sending text
Sleep, 300
Send, {enter}
Sleep, 5000
; If the title of the window changes after this, you should use:
; WinWait, new title
; WinActivate, new title
; WinWaitActive, new title
Click, 149, 355
; ... continue using one of the next options
; ...
return
First option - Send username and password directly (without reading a file):
SendInput, username
Sleep, 300
Click, 172, 455 ; or Send, {Tab} if it activates the password field
Sleep, 300
SendInput, password
Click, 87, 507 ; or Send, {enter} if it activates the log-in field
Second option - If you have to read username and password from a file:
FileReadLine, OutputVar, accounts.txt, 1 ; If username|password (without spaces) is the first line in this file
usrnme := StrSplit(OutputVar,"|").1
pwd := StrSplit(OutputVar,"|").2
SendInput, %usrnme%
Sleep, 300
Click, 172, 455 ; or Send, {Tab} if it activates the password field
Sleep, 300
SendInput, %pwd%
Sleep, 300
Click, 87, 507 ; or Send, {enter} if it activates the log-in field

Wait for previous process to finish before starting new one

I need to find a way in AHK to wait for a program to finish, before starting a new one.
Basically, I have a script that opens an application and inputs some parameters. The application then spends an unknown amount of time processing the input data.
Unfortunately, at the moment the ahk script ends before the application has finished processing, at which point the same ahk script is run again and does not work / interrupts the previous processing.
edit: (the ahk .exe is called using subprocess calls in Python)
is there a way or any methods to help with this?
For reference, the script:
#NoEnv
CoordMode, Mouse, Window
SendInput Mode Input
#SingleInstance Force
SetTitleMatchMode 2
#WinActivateForce
SetControlDelay 1
SetWinDelay 0
SetKeyDelay -1
SetMouseDelay -1
SetBatchLines -1
if 0 < 2 ; The left side of a non-expression if-statement is always the name of a variable.
{
MsgBox, This script requires 2 incoming parameters but it only received %0%.
ExitApp
}
IfWinNotExist, ahk_exe photoscan.exe
{
Run, "C:\Program Files\Agisoft\PhotoScan Pro\photoscan.exe"
}
sleep, 200
WinActivate, ahk_exe photoscan.exe
sleep,5
WinMaximize, ahk_exe photoscan.exe
;Macro5:
Click, 476, 438, 0
SendInput {LControl Down}
SendInput {r}
Click, -56, 157, 0
WinActivate, Run Python Script ahk_class QWidget
sleep, 400
SendInput {LControl Up}
SendInput {LControl Down}
SendInput {a}
SendInput {LControl Up}
sleep, 400
SendInput {Backspace}
SendInput %1% ; 1st argument is the photoScan API scriptimages folder directory
SendInput {Tab}
SendInput {Tab}
sleep, 400
SendInput {LControl Down}
SendInput {a} ; 2nd argument is additional args (in our case, the projectName)
SendInput {LControl Up}
SendInput {Backspace}
SendInput %2% ; 2nd argument is the images folder directory & name of output log, model and texture
Sleep, 703
SendInput {Enter}
Click, 476, 438, 0
Return
You have:
IfWinNotExist, ahk_exe photoscan.exe
{
Run, "C:\Program Files\Agisoft\PhotoScan Pro\photoscan.exe"
}
sleep, 200
Which is set to start/launch the application if it is not running. Then a sleep to allow two tenths of a second for it to load (which is probably too small).
Instead of just a ‘sleep’ you have to ‘WinWait’ or ‘WinWaitActive’, found at this link:
https://autohotkey.com/docs/commands/WinWaitActive.htm
Like this sample:
Run, "C:\Program Files\Agisoft\PhotoScan Pro\photoscan.exe"
WinWaitActive, ahk_exe photoscan.exe, , 2
if ErrorLevel
{
MsgBox, WinWait timed out.
return
}
else
WinMinimize ; minimize the window found by WinWaitActive.
You may also have to use the window inspector to get the true name of the window/application/process name.

AHK - How to hold a macro while Physical Key depressed

What I want to do is this:
Numpad3::
if(not GetKeyState("Shift" , "P") and not GetKeyState("RButton" , "P"))
{
SendInput {Shift down}
Sleep, 33
Click down right
}
Return
Numpad3 Up::
Sleep, 100
Click up right
Sleep, 33
SendInput {Shift up}
Return
But for some reason it isn't canceling when I let the button up. :(
I would suggest to use Send {RButton Down} (or Up) to send the right mouse click, instead of Click up right.
Also, you don't want to be sending random Sleep's if they are not really necessary, as it creates lag and makes the script inelegant and potentially unreadable.
Here is code which sends Control instead of RButton but it's only so I can test it within Notepad++.
Just replace Control with RButton and have a go:
*NumpadPgDn::
*Numpad3::
Send {Shift Down}{Control Down}
return
*NumpadPgDn Up::
*Numpad3 Up::
Send {Shift Up}{Control Up}
return