Dual monitor help needed [AutoHotkey] - autohotkey

I'm having trouble getting my script to work on multiple monitors, having searched and found some posts regarding the use of multiple monitors I''m still not sure where I am going wrong and how to fix it.
I am currently using a laptop with an external monitor connected, but I will be sharing this with colleagues who may not have additional monitors. When I run on an application on the main screen (Laptop screen) everything seems to work as expected but when I run it on an application on the additional monitor the coordinates seem to be off.
Please see my code below, I know this may be a mess and could be cleaned up but I'm not quite that knowledgable yet.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
CoordMode, Pixel, Screen
CoordMode, Mouse, Screen
If !FileExist( "Settings.ini" ) {
If ( WinExist("Amazon WorkSpaces") )
{
WinActivate
} Else
{
MsgBox, 48, Auto Clicker, Open AWS!
}
MsgBox Please close this message and click Start Tracing button
KeyWait, LButton, Down
MouseGetPos, tracingx, tracingy
KeyWait, LButton, Up
MouseGetPos, tracingendx, tracingendy
AHKCommand = %tracingx%, %tracingy%
IniWrite, %tracingx%, Settings.ini, tracing, xcoord
IniWrite, %tracingy%, Settings.ini, tracing, ycoord
MsgBox Please close this message and click Back to consignment list button
KeyWait, LButton, Down
MouseGetPos, backx, backy
KeyWait, LButton, Up
MouseGetPos, backendx, backendy
AHKCommand2 = %backx%, %backy%
IniWrite, %backx%, Settings.ini, back, xcoord
IniWrite, %backy%, Settings.ini, back, ycoord
InputBox, minrefresh, Minimum Refresh, Enter Minimum refresh time in milliseconds (1 min = 60000 milliseconds), , , , , , , , 180000
IniWrite, %minrefresh%, Settings.ini, refresh rates, min
InputBox, maxrefresh, Maximum Refresh, Enter Maximum refresh time in milliseconds (1 min = 60000 milliseconds), , , , , , , , 300000
IniWrite, %maxrefresh%, Settings.ini, refresh rates, max
Return ; This stops the script or returns from the above subroutine.
; ExitApp ; This exits the script entirely
; GoSub, Start ; This jumps to the label start in the script.
; Use non of these to continue the script
}
InputBox, minrefresh, Minimum Refresh, Enter Minimum refresh time in milliseconds (1 min = 60000 milliseconds), , , , , , , , 60000
IniWrite, %minrefresh%, Settings.ini, refresh rates, min
InputBox, maxrefresh, Maximum Refresh, Enter Maximum refresh time in milliseconds (1 min = 60000 milliseconds), , , , , , , , 180000
IniWrite, %maxrefresh%, Settings.ini, refresh rates, max
^+z:: ; Control+Shift+Z hotkey.
IniRead, tracingx, Settings.ini, tracing, xcoord
IniRead, tracingy, Settings.ini, tracing, ycoord
IniRead, backx, Settings.ini, back, xcoord
IniRead, backy, Settings.ini, back, ycoord
AHKCommand = %tracingx%, %tracingy%
AHKCommand2 = %backx%, %backy%
Random, rand, %minrefresh%, %maxrefresh%
Loop {
If ( WinExist("Amazon WorkSpaces") )
{
WinActivate
PixelGetColor, color, %tracingx%, %tracingy%
If (color = 0xEFEFEF) {
Click %AHKCommand%
Sleep, 2000
PixelGetColor, color, %backx%, %backy%
If (color = 0xF5F5F5) {
Click %AHKCommand2%
Sleep, 2000
} Else
{
MsgBox, , Auto Clicker, You have a call!
}
} Else
{
MsgBox, 48, Auto Clicker, Check Settings!]
}
} Else
{
MsgBox, 48, Auto Clicker, Open AWS!
}
Sleep, %rand%
}
What I hope to happen is on starting the script it checks for settings and if it doesn't find them it will ask you for the information. once this check is done it will click a set location from the data you provided at an interval set by yourself and check it matches the specific colour (button present/not present) then displays errors or messages as required. Pretty simple so far?
The problem comes when I have the application on the additional monitor. At first, I thought nothing was happening, but with a msgbox here and there I can now see that the coordinates I selected during setup are correct but when the script is running the coordinates seem to be off by a varying amount (Currently between 105 & 120px on the x-axis and between 145 & 147px on the y-axis.
Is this going to work, or should I give up and get everyone using it on the main laptop screen?

Related

while loop not executing correctly when toggled on/off

Goals:
Run ahk script so that a window stays active. When the user clicks off the window it immediately becomes active again.
This is so an overlay (considered its own window) can be used in a game and that if the overlay is clicked on by accident the game window will become the active window again.
I would also like this to be able to be turned on and off during game play so that the user can alt+tab if necessary.
Problems:
I'm testing my code implementation, so far i have it set up to make a blank notepad file become the active window and stay active.
The problem is the toggle (ctrl+alt+J). I can toggle the code it off just fine but when i toggle it on the window doesn't become active again.
Code:
stop := 0
; 0 = off, 1 = on
while (stop = 0)
{
IfWinNotActive, Untitled - Notepad
{
WinActivate, Untitled - Notepad
}
}
return
^!j::
stop := !stop
if (stop = 0){
MsgBox, stop is off.
}
else{
MsgBox, stop is on.
}
return
The reason it doesn't work after you toggle it off is that While only runs until is evaluates to false. Even if what it would evaluate later becomes true again, it won't restart.
Here's what you can do to make your current code work:
stop := 0
; 0 = off, 1 = on
labelWinCheck: ; label for GoSub to restart while-loop
while (stop = 0)
{
IfWinNotActive, Untitled - Notepad
{
WinActivate, Untitled - Notepad
}
Sleep , 250 ; added sleep (250 ms) so CPU isn't running full blast
}
return
^!j::
stop := !stop
if (stop = 0){
MsgBox, stop is off.
} else {
MsgBox, stop is on.
}
GoSub , labelWinCheck ; restarts while-loop
return
There are a couple of different ways that I would look at to achieve your goal.
Easy: use SetTimer instead of While.
stop := 0
SetTimer , labelWinCheck , 250 ; Repeats every 250 ms
labelWinCheck:
If !WinActive( "Untitled - Notepad" )
WinActivate , Untitled - Notepad
Return
^!j::
SetTimer , labelWinCheck , % ( stop := !stop ) ? "off" : "on"
MsgBox , % "stop is " . ( stop ? "on" : "off" )
Return
Advanced: us OnMessage() to monitor WinActivate events. I don't have a working example of this as that would take a bit of research for me, but here is a link for a solution I made to monitor keyboard events, Log multiple Keys with AutoHotkey. The links at the bottom may especially prove useful.

pixelsearch and click right pixel

IF NOT A_IsAdmin ; Runs script as Admin.
{
Run *RunAs "%A_ScriptFullPath%"
ExitApp
}
#MaxThreadsPerHotkey, 2
CoordMode, Pixel, Screen
#singleInstance, Force
toggle = 0
upperLeftX := 750
upperLeftY := 400
lowerRightX := 850
lowerRightY := 500
F8:: ; press F8 to toggle the loop on/off.
SoundBeep
Toggle := !Toggle
While Toggle
{ ;-- Begin of loop.
PixelSearch, X, Y,%upperLeftX%, %upperLeftY%, %lowerRightX%, %lowerRightY%, 0x000000, 0, Fast RGB
IF ErrorLevel = 1 ; IF NOTFound.
{
sleep, 100
}
IF ErrorLevel = 0 ; IF Found.
{
MouseClick, left
sleep, 300
}
} ;-- End of Loop.
return
F8 starts loop and this code checks specific pixel in rectangle and sends left click.
It works with [MouseClick, left, %X%, %Y%].But I want to know how can I use dllcall mouse event to click on specific pixel.
for example
DllCall("mouse_event",uint,1,int,%X%,int,%Y%,uint,0,int,0)
But its not working
I doubt that you actually want to do this via DLL calls. mouse_event doesn't even take coordinates, but values between 0-65535.
If you want to be able to click any pixel on the screen make sure you set it to be relative to the screen: CoordMode, Mouse, Screen
Then use ControlClick/PostMessage/SendMessage if you don't want to affect your mouse pointer by that click. Or use MouseClick/Click. Or MouseMove+Send, {LButton}.

Temporarily Pause Autofire loop on holding button

I wrote a script that sends autofire left clicks and can be triggered on and off. The script works. However, the problem is that holding the right mouse button does not work properly anymore because the left click keeps getting sent. So I want to change the script that it gets temporarily paused while I hold down the right mouse button.
How would I go about doing this? Here is my current code:
#MaxThreadsPerHotkey 3
#z::
#MaxThreadsPerHotkey 1
if keep_winz_running = y
{
keep_winz_running = n
return
}
; Otherwise:
keep_winz_running = y
Loop
{
GetKeyState, rbut, Rbutton
If rbut, = U
{
Loop,
{
MouseClick, left
Sleep, 50 ;This means the script will wait 1.5 secs
if keep_winz_running = n ; The user signaled the loop to stop.
break ; break out of the loop
}
Timers are the best!
sendToggle := false
#z::
if(!sendToggle) {
sendToggle := true
SetTimer, SendClick, 100
} else {
sendToggle := false
SetTimer, SendClick, Off
}
return
#If sendToggle
RButton::
SetTimer, SendClick, Off
KeyWait, RButton
SetTimer, SendClick, 100
return
SendClick:
Click
return
I find the send interval of 50 ms awfully fast, especially since you won't be able to actually reach 50 ms without reducing SetBatchLines and SetKeyDelay. If it really needs to be that fast, consider changing them.

Can someone help me an AutoHotKey script?

I've read the help and guide for it but I just can't figure it out. All I want to do is create a hotkey that when pressed will move my mouse until the hotkey is pressed again. Can anyone tell me how to do this? It should be really simple but apparently I'm missing something.
This is pretty much the most annoying HotKey ever, but here you go (hotkey is Ctrl+Alt+C);
#MaxThreadsPerHotkey 3
^!c::
#MaxThreadsPerHotkey 1
if DoMouseMove
{
DoMouseMove := false
return
}
DoMouseMove := true
Loop
{
Sleep 100
Random, randX, 1, 1028
Random, randY, 1, 800
MouseMove, randX, randY, 25
Sleep, 100
if not DoMouseMove
break
}
DoMouseMove := false
return
I will throw in my solution.
pause::
If (Toggle := !Toggle) ; Toggle the value True/False
{
ToolTip Mouse Mover,A_ScreenWidth/2,0 ; Show that Mouse Mover is active
SetTimer MoveMouse, 1000 ; 1000 ms = 1 sec. Every minute (60000 ms) is probably enough.
}
Else
{
Tooltip ; Turn Mouse Mover alert window off
SetTimer MoveMouse, Off ; Turn the timer off
}
return
MoveMouse:
MouseMove, 1, 0, 1, R ;Move the mouse one pixel to the right
Sleep, 50 ; Wait 50 ms. Not realy required, but makes the move visible
MouseMove, -1, 0, 1, R ;Move the mouse back one pixel
return

Autohotkey loop not working

My loop in my autohotkey script is only running through once. Can anyone tell me why? Thanks
Loop, 8
{
WinActivate, NDTr
ControlClick, Button3 ;Select Batch, enter info, start collecting data
WinWait, Batch Readings
ControlClick, Edit1
Send {BS}+{BS}+{BS}+{BS}+{BS}+{BS}
Send 1
ControlClick, Edit2
Send {BS}+{BS}+{BS}+{BS}+{BS}+{BS}
Send 15
if A_Index = 4
{
Sleep, 20000
}
else if A_Index = 7
{
Sleep, 20000
}
else if A_Index = 1
{
Sleep, 3000
}
else
{
Sleep, 15000
}
ControlClick, Button1
Sleep, 15000
}
WinWait looks like a likely culprit like anthv123 said. Double check your window's title and make sure it fits the TitleMatchMode that you're expecting.
Common debugging practices include adding different ToolTips in places along the problem code. For example tooltips above and below the WinWait line with texts "before" and "after" would tell you if it's pausing indefinitely at that part (if it never says "after").
Sleeping for 3-20 seconds isn't going to help your patience either.
Try using this to diagnose the issue. If "Batch Readings" takes longer than 5 seconds, you get an error letting you know and the loop continues
WinWait, Batch Readings,,5
if (errorLevel = 1)
Msgbox % "Batch Readings timed out"