AHK "PixelGetColor" Constantly Returning True - autohotkey

For starters, I'm really new to AutoHotKey. I was making a script that looks for a color (with a little variance) at a specific coordinate, & if it finds that color, type the specified number.
It should continuously sift through the five coordinate spots in the loop and send the number that matches the color, but it finds the number every single time. Just a constant stream of "123451234512345" I've tried completely removing the color from the screen, but it still manages to find it.
I'm sure that I probably have something wrong with my code. Getting a headache trying to figure out what. Would love some help.
Loop
{
CoordMode, Pixel, Screen
PixelGetColor, color1x, color1y, 200, 200, 200, 200, 0xFF0000, 3, FastRGB
if ErrorLevel = 0
Send, 1
else
CoordMode, Pixel, Screen
PixelGetColor, color2x, color2y, 400, 400, 400, 400, 0xFF0000, 3, FastRGB
if ErrorLevel = 0
Send, 2
else
CoordMode, Pixel, Screen
PixelGetColor, color3x, color3y, 600, 600, 600, 600, 0xFF0000, 3, FastRGB
if ErrorLevel = 0
Send, 3
else
CoordMode, Pixel, Screen
PixelGetColor, color4x, color4y, 800, 800, 800, 800, 0xFF0000, 3, FastRGB
if ErrorLevel = 0
Send, 4
else
CoordMode, Pixel, Screen
PixelGetColor, color5x, color5y, 1000, 1000, 1000, 1000, 0xFF0000, 3, FastRGB
if ErrorLevel = 0
Send, 5
else
return
}
Numpad9::pause
esc::ExitApp

There are a couple of things that are wrong with your code:
You're using PixelGetColor incorrectly. It stores the color of the pixel at the desired coordinates in OutputVar, not compare the color of the pixel at that coordinate with a specified color.
You're checking the ErrorLevel. It's set to 1 if there's a problem or 0 otherwise.
If you need to scan the five locations for each loop, there's no need for the else statement (you're also using it incorrectly in this case).
As what 0x464e said, you need to state CoordMode only once at the start of the script.
In your case, PixelGetColor always succeeds in getting the color of the pixel, which means ErrorLevel is always set to zero. This gives you the impression that it's always "returning true".
You should be checking the OutputVar instead. Try this:
DESIRED_COLOR := "0xFF0000"
CoordMode, Pixel, Screen
Loop
{
PixelGetColor, color1, 200, 200
if (color1 = DESIRED_COLOR)
Send, 1
PixelGetColor, color2, 400, 400
if (color2 = DESIRED_COLOR)
Send, 2
PixelGetColor, color3, 600, 600
if (color3 = DESIRED_COLOR)
Send, 3
PixelGetColor, color4, 800, 800
if (color4 = DESIRED_COLOR)
Send, 4
PixelGetColor, color5, 1000, 1000
if (color5 = DESIRED_COLOR)
Send, 5
}
Numpad9::pause
esc::ExitApp

Related

How to use pixelsearch?

I have been trying to put together this script that clicks on the pixel with the specified color.
It keeps crashing and clicking unrelated spots.
Is there a better way to implement this? This is what I have (sorry i'm very new to this)
Loop {
PixelSearch, OutputVarX, OutputVarY, 400, 300, 1800, 800, 821A83, Fast
if (ErrorLevel){
MsgBox, no
}
else if (!ErrorLevel)
{
Click, %OutputVarX%, %OutputVarY% Down
Sleep 2000
Click, Up
}
} Until, limit > 0
limit = 0
^w::
limit += 1
return
I answered a similar post a little while ago that might help you (AHK) Can't seem to get a pixel color statement working. Basically using a Timer instead of a Loop would probably be more helpful to you. I edited your code below to what I think might work, but still believe the Timer is a better solution (command SetTimer).
CoordMode, Mouse, Screen ; Or 'Relative' as you desire
CoordMode, Pixel, Screen
; this tells the the pixel search to be relative to the screen
; and the mouse click as well. that might be what is missing here.
Loop {
PixelSearch, OutputVarX, OutputVarY, 400, 300, 1800, 800, 0x821A83, Fast ; decimal or hexadecimal (including "0x" prefix)
if (ErrorLevel) {
MsgBox, no
}
else if (!ErrorLevel)
{
Click, %OutputVarX%, %OutputVarY%, Down
Sleep 2000
Click, Up
}
} Until (limit > 0)
limit = 0
Return
; each block should have a Return unless you want it
; to drop into the code below
^w::
limit += 1
return

My script breaks down at some point, I've eliminated all the syntax errors the debugger was able to spot

This is a script that is supposed to use the windows snipping tool to sequentially screencap pictures from an online gallery. If anyone can spot the problem that would be much appreciated.
#SingleInstance, Force
a := 112
name :=1
x:: Pause, Toggle
y:: ExitApp
Loop, a
{
MouseClickDrag, Left, 1300, 210, 645, 140
Sleep, 100
MouseClick, Left, 1277, 1038, 0, 5
sleep, 100
MouseClick, Left, 838, 64, 0, 5
sleep, 100
SendInput, %name%
name ++
sleep, 100
SendInput, {Enter}
Sleep, 100
MouseClickDrag, Left, 670, 13, 1393, 153
Sleep, 100
MouseClick, Left, 500, 490, 0, 5
Sleep, 300
MouseClick, Left, 500, 490, 0, 5
SendInput, {Right}
}
Two problems in it.
Firstly, your loop is unreachable code.
Code execution stops when your first hotkey label is encountered. This is called the Auto-execute Section.
Secondly, loop doesn't take an expression to the first parameter. It takes a legacy text parameter. So you'd either want to use the legacy way of referring to a variable, which would be %a%, but personally I'd push you towards using the modern expression syntax and forcing an expression to that parameter by starting the parameter off with a % followed up by a space. So Loop, % a.
To read more about legacy syntax vs expression syntax, see this page of the documentation.
Here's your fixed script:
#SingleInstance, Force
a := 112
name := 1
Sleep, 3000
Loop, % a
{
MouseClickDrag, Left, 1300, 210, 645, 140
Sleep, 100
MouseClick, Left, 1277, 1038, 0, 5
Sleep, 100
MouseClick, Left, 838, 64, 0, 5
Sleep, 100
SendInput, % name
name++
Sleep, 100
SendInput, {Enter}
Sleep, 100
MouseClickDrag, Left, 670, 13, 1393, 153
Sleep, 100
MouseClick, Left, 500, 490, 0, 5
Sleep, 300
MouseClick, Left, 500, 490, 0, 5
SendInput, {Right}
}
;this return here ends the auto-execute section
;but of course, in this specific case it's totally
;useless since the next line is a hotkey label
;which would also stop the auto-execute section
return
;even though the code execution gets stuck inside the loop,
;hotkeys can be specified down here
;they're created even before the auto-execute section starts
x::Pause, Toggle
y::ExitApp

Unstoppable script Issue

I have a script wich uses several mousemoves and, when needed, I press F3 to stop the moves forcing a reload or ESC to stop the moves exiting the app. It works fine with no issues in the regular speed.
The problem is: when I decrease the mousespeed and increase the mousedelay, the script becomes unstoppable: I press the F2, F3 and ESC keys several times (trying to make it stops) but the script ignores it and continues running the mousemoves.
Here's a minimal example of my problem:
SendMode Input
$F1::
SetDefaultMouseSpeed, 50
SetMouseDelay, 30
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
Mousemove, 200, 200
Mousemove, 600, 600
SoundPlay, *48
return
$F2:: Pause
$F3:: Reload
$ESC:: ExitApp
Why does it happens and how can I fix it (how can I stop the script even with low speed+high delay)?
ps: F1 key starts the mousemoves sequence.
MouseMove with non-zero speed cannot be interrupted by another hotkey inside the same AHK script because Autohotkey is single-threaded internally (it just emulates thread-like behavior) and performs a blocking sleep for each mouse micromovement until it reaches the overall distance you specified.
Solutions:
Check whether a hotkey was pressed after each MouseMove, but it's non-instantaneous;
Implement your own MouseMove that checks GetKeyState after each 1px movement;
Use a master script with hotkeys that run/pause/stop the child:
Stopping: trivial, use Process Close
Running: the child should hide tray icon otherwise it'll stay after process close
Pausing: nontrivial but there are solutions (see also the underlying mechanics).

My ahk code not working

F1::pause,toggle
F2::
Loop,
{
PixelSearch, Px, Py, 432, 298, 444, 286, 0xFFEB63, 3, Fast
if (errorlevel = 0)
{
Sleep 5000
Click 1040,638
Sleep 1500
Click 1055,288
Sleep 10000
}
else{
sleep 3000
Click 1136, 642
sleep 10000
}
}
When I press F2 It should search for 0xFFEB63 in area.If color is not there then click 1136,642.At least,that was what I wanted to do.It directly jumps to else part.
ErrorLevel is set to 0 if the color was found in the specified region, 1 if the color was not found, or 2 if there was a problem that prevented the command from conducting the search.
https://autohotkey.com/docs/commands/PixelSearch.htm#ErrorLevel
F2::
Loop,
{
PixelSearch, Px, Py, 432, 298, 444, 286, 0xFFEB63, 3, Fast
if (errorlevel = 0) ; If color is found in the first area
{
Sleep 5000
Click 1040,638
Sleep 1500
Click 1055,288
Sleep 10000
}
else
if (errorlevel = 1) ; If color is not in the first area
{
sleep 3000
Click 1136, 642
sleep 10000
}
; else ; if (errorlevel = 2)
; do sth else
}
return
EDIT:
You should use
CoordMode, Pixel, Screen
in the autoexecute-section, unless you want the Coordinates to be relative to the active window.

Position splash text or message box

I am using two monitors and the message boxes always appear in the middle of the primary screen, regardless of where the active window is.
How can I specify the position of a Splash Text box or Message box so that it shows in the middle of the active window, not in the middle of the primary monitor?
You can try this:
#Persistent
AppName=Move
Menu, Tray, Tip, %AppName%
Menu, Tray, Icon , Shell32.dll, 26, 1 ; 45, 28, 113, 74, 134
^w::
WinGetPos, X, Y, Width, Height, A
Mx:=X + (Width/2) -100
My:=Y + (Height/2) -100
SetTimer, MoveMsgBox, -50
MsgBox, ,%AppName%, %X% %Y% OK
Return
MoveMsgBox:
WinMove, %AppName%, , %Mx% , %My%
Return