This will check X,Y position for a RGB color and if found trigger the hotkey. You can create multiple threads for different locations. Dunno if anyone else would find this useful,but here goes nothing
Code: Select all
; Copyright © 2023 Faren <farendil2020@gmail.com>
; This work is free. You can redistribute it and/or modify it under the
; terms of the Do What The Fuck You Want To Public License, Version 2,
; as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
#include <JSON>
;OPTIMIZATIONS START
#NoEnv
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
#Warn
ListLines Off
Process, Priority, , A
SetBatchLines, -1
SetKeyDelay, -1, -1
SetMouseDelay, -1
SetDefaultMouseSpeed, 0
SetWinDelay, -1
SetControlDelay, -1
SendMode Input
SetWorkingDir %A_ScriptDir%
DetectHiddenWindows, on
;OPTIMIZATIONS END
CoordMode, Pixel, Screen
CoordMode, Mouse, Screen
pixelSearchMode = "RGB"
global splashFile := ".\recycle.png"
file := ".\actions.ini"
; sample file format listed at end of script
toggle := 0,
paused := 0,
global debug := 0
global error := 1
global actions := []
global actionsJSON
global numThreads := 0
Loop read, %file%
{
if SubStr(A_LoopReadLine,1,2)=="//" or SubStr(A_LoopReadLine,1,1)==";"
continue
subarray := StrSplit(A_LoopReadLine, "csv")
if SubStr(subarray,1,2)=="//"
continue
if SubStr(subarray,1,1)==";"
continue
actions.Insert(subarray)
}
actionsJSON = % JSON.Dump(actions)
global PID1:=0, pname1, execScript1,
PID2:=0, pname2, execScript2,
numThreads := 2
execScript1 := buildScript(1, 637, 521, 30, 225, 670, "Secondary")
execScript2 := buildScript(2, 637, 477, 45, 200, 690, "Main")
^!r::Reload ; Ctrl+Alt+R
;=============================================================================
; alt-` : One-Key Rotation (Single Target)
;#ifWinActive <Window Title>
`::
toggle := !toggle
if (toggle) {
Loop, %numThreads% {
DetectHiddenWindows, on
script := execScript%A_Index%
sname = script%A_Index%
PID := ExecScript(script,[actionsJSON],A_AhkPath).ProcessID
PID%A_Index% := PID
WinWait, ahk_pid %PID%
WinGetTitle, pname%A_Index%, ahk_pid %PID%
}
} else {
killCMD := "/c taskkill /F"
loop, %numThreads% {
pid = PID%A_Index%
killCMD .= " /PID "%pid%
}
killCMD .= " /T && exit"
run, %comspec% %killCMD%,, hide
}
ScriptStatus(toggle)
return
!`::
paused := !paused
loop, %numThreads% {
pname := pname%A_Index%
pauseSuspendScript(pname, paused, paused)
}
return
buildScript(script, X:=0, Y:=0, delay:=0, tipX:=0, tipY:=0, desc="") {
var1 =
( %
#include <JSON>
;OPTIMIZATIONS START
#NoTrayIcon
#NoEnv
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
#Warn
ListLines Off
Process, Priority, , A
SetBatchLines, -1
SetKeyDelay, -1, -1
SetMouseDelay, -1
SetDefaultMouseSpeed, 0
SetWinDelay, -1
SetControlDelay, -1
SendMode Input
SetWorkingDir %A_ScriptDir%
DetectHiddenWindows, on
CoordMode, Pixel, Screen
CoordMode, Mouse, Screen
;OPTIMIZATIONS END
global pixelSearchMode = "RGB"
actionsJSON = %1% ; arg sent as a JSON version of actions array
global myactions := JSON.Load(actionsJSON)
loop {
)
var2 = checkPixel(%X%, %Y%, %script%, %tipX%, %tipY%, %delay%)
var3 =
( %
}
checkPixel(Byref X, Byref Y, Byref script, Byref tipX, Byref tipY, delay:=0) {
PixelGetColor, pColor, X, Y, %pixelSearchMode%
for _, vAction in myactions {
while (GetKeyState("LShift", "P")){
}
if ((vAction.5 = 0) or (vAction.5 = script)) {
if (pColor = vAction.2) {
; Can uncomment this to see whats being triggered in a tooltip
; tooltip % script ": " vAction.1 ": " vAction.4 , tipX, tipY
send % vAction.4
break
}
}
}
DllCall("Sleep","UInt",delay)
}
)
execScript := var1 "`n" var2 "`n" var3
return execScript
}
;=============================================================================
;
ScriptStatus(mode) {
if (mode) {
Splashimage, %splashFile%, B W50 H50 X750 Y1,,, ScriptStatus
} else {
SplashImage, Off
}
}
;=============================================================================
;
Log(text,newline) {
OutputDebug % "AHK| " text
if (newline)
OutputDebug % "`n"
}
;=============================================================================
;
StrSplit(InputVar, Delimiter=",", OmitChars=" `t") {
array := []
Loop Parse, InputVar, %Delimiter%, %OmitChars%
array.Insert(A_LoopField)
return array
}
;=============================================================================
; return difference in 2 rgb colors
ColorDiff(color1, color2, mode:=0) {
Format:=A_FormatInteger
SetFormat, Integer, hex
r1:=color1>>16, r2:=color2>>16
g1:=color1>>8&0xFF, g2:=color2>>8&0xFF
b1:=color1&0xFF, b2:=color2&0xFF
SetFormat,Integer, % Format
diffr:=Abs(r1 - r2), diffg:=Abs(g1 - g2), diffb:=Abs(b1 - b2)
if mode=1
return diffr+diffg+diffb
else return diffr>diffg&&diffr>diffb?diffr:diffg>diffb?diffg:diffb
}
;=============================================================================
; pauseSuspendScript(ScriptTitle, suspendHotkeys := False, pauseScript := False)
pauseSuspendScript(Byref ScriptTitle, suspendHotkeys := False, pauseScript := False) { ;-- function to suspend/pause another script
prevDetectWindows := A_DetectHiddenWindows
prevMatchMode := A_TitleMatchMode
DetectHiddenWindows, On
SetTitleMatchMode, 2
if (script_id := WinExist(ScriptTitle " ahk_class AutoHotkey")) {
; Force the script to update its Pause/Suspend checkmarks.
SendMessage, 0x211,,,, ahk_id %script_id% ; WM_ENTERMENULOOP
SendMessage, 0x212,,,, ahk_id %script_id% ; WM_EXITMENULOOP
; Get script status from its main menu.
mainMenu := DllCall("GetMenu", "uint", script_id)
fileMenu := DllCall("GetSubMenu", "uint", mainMenu, "int", 0)
isPaused := DllCall("GetMenuState", "uint", fileMenu, "uint", 4, "uint", 0x400) >> 3 & 1
isSuspended := DllCall("GetMenuState", "uint", fileMenu, "uint", 5, "uint", 0x400) >> 3 & 1
DllCall("CloseHandle", "uint", fileMenu)
DllCall("CloseHandle", "uint", mainMenu)
if (suspendHotkeys && !isSuspended) || (!suspendHotkeys && isSuspended)
PostMessage, 0x111, 65305, 1,, ahk_id %script_id% ; this toggles the current suspend state.
if (pauseScript && !isPaused) || (!pauseScript && isPaused)
PostMessage, 0x111, 65403,,, ahk_id %script_id% ; this toggles the current pause state.
}
DetectHiddenWindows, %prevDetectWindows%
SetTitleMatchMode, %prevMatchMode%
return script_id
}
/* ===========================================================================
* Function: ExecScript
* Run/execute AutoHotkey script[file, through named pipe(s) or from stdin]
* Mod of/inspired by HotKeyIt's DynaRun()
* License:
* WTFPL [http://wtfpl.net/]
* Syntax:
* exec := ExecScript( code [ , args, kwargs* ] )
* Parameter(s)/Return Value:
* exec [retval] - a WshScriptExec object [http://goo.gl/GlEzk5]
* if WshShell.Exec() method is used else 0 for
* WshShell.Run()
* script [in] - AHK script(file) or code(string) to run/execute.
* When running from stdin(*), if code contains
* unicode characters, WshShell will raise an
* exception.
* args [in, opt] - array of command line arguments to pass to the
* script. Quotes(") are automatically escaped(\").
* kwargs* [in, variadic] - string in the following format: 'option=value',
* where 'option' is one or more of the following
* listed in the next section.
* Options(kwargs* parameter):
* ahk - path to the AutoHotkey executable to use which is relative to
* A_WorkingDir if an absolute path isn't specified.
* name - when running through named pipes, 'name' specifies the pipe name.
* If omitted, a random value is generated. Otherwise, specify an
* asterisk(*) to run from stdin. This option is ignored when a file
* is specified for the 'script' parameter.
* dir - working directory which is assumed to be relative to A_WorkingDir
* if an absolute path isn't specified.
* cp - codepage [UTF-8, UTF-16, CPnnn], default is 'CP0'. 'CP' may be
* omitted when passing in 'CPnnn' format. Omit or use 'CP0' when
* running code from stdin(*).
* child - if 1(true), WshShell.Exec() method is used, otherwise .Run().
* Default is 1. Value is ignored and .Exec() is always used when
* running code from stdin.
* Example:
* exec := ExecScript("MsgBox", ["arg"], "name=some_name", "dir=C:\Users")
* Credits:
* - Lexikos for his demonstration [http://goo.gl/5IkP5R]
* - HotKeyIt for DynaRun() [http://goo.gl/92BBMr]
*/
ExecScript(Byref script, args:="", kwargs*) {
;// Set default values for options first
child := true ;// use WshShell.Exec(), otherwise .Run()
, name := "AHK_" . A_TickCount
, dir := ""
, ahk := A_AhkPath
, cp := 0
for i, kwarg in kwargs
if ( option := SubStr(kwarg, 1, (i := InStr(kwarg, "="))-1) )
; the RegEx check is not really needed but is done anyways to avoid
; accidental override of internal local var(s)
&& ( option ~= "i)^child|name|dir|ahk|cp$" )
%option% := SubStr(kwarg, i+1)
pipe := (run_file := FileExist(script)) || (name == "*") ? 0 : []
Loop % pipe ? 2 : 0
{
;// Create named pipe(s), throw exception on failure
if (( pipe[A_Index] := DllCall(
(Join, Q C
"CreateNamedPipe" ; http://goo.gl/3aJQg7
"Str", "\\.\pipe\" . name ; lpName
"UInt", 2 ; dwOpenMode = PIPE_ACCESS_OUTBOUND
"UInt", 0 ; dwPipeMode = PIPE_TYPE_BYTE
"UInt", 255 ; nMaxInstances
"UInt", 0 ; nOutBufferSize
"UInt", 0 ; nInBufferSize
"Ptr", 0 ; nDefaultTimeOut
"Ptr", 0 ; lpSecurityAttributes
)) ) == -1) ; INVALID_HANDLE_VALUE
throw Exception("ExecScript() - Failed to create named pipe", -1, A_LastError)
}
; Command = {ahk_exe} /ErrorStdOut /CP{codepage} {file}
static fso := ComObjCreate("Scripting.FileSystemObject")
static q := Chr(34) ;// quotes("), for v1.1 and v2.0-a compatibility
cmd := Format("{4}{1}{4} /ErrorStdOut /CP{2} {4}{3}{4}"
, fso.GetAbsolutePathName(ahk)
, cp="UTF-8" ? 65001 : cp="UTF-16" ? 1200 : cp := Round(LTrim(cp, "CPcp"))
, pipe ? "\\.\pipe\" . name : run_file ? script : "*", q)
; Process and append parameters to pass to the script
for each, arg in args
{
i := 0
while (i := InStr(arg, q,, i+1)) ;// escape '"' with '\'
if (SubStr(arg, i-1, 1) != "\")
arg := SubStr(arg, 1, i-1) . "\" . SubStr(arg, i++)
cmd .= " " . (InStr(arg, " ") ? q . arg . q : arg)
}
if cwd := (dir != "" ? A_WorkingDir : "") ;// change working directory if needed
SetWorkingDir %dir%
static WshShell := ComObjCreate("WScript.Shell")
exec := (child || name == "*") ? WshShell.Exec(cmd) : WshShell.Run(cmd)
if cwd ;// restore working directory if altered above
SetWorkingDir %cwd%
if !pipe ;// file or stdin(*)
{
if !run_file ;// run stdin
exec.StdIn.WriteLine(script), exec.StdIn.Close()
return exec
}
DllCall("ConnectNamedPipe", "Ptr", pipe[1], "Ptr", 0) ;// http://goo.gl/pwTnxj
DllCall("CloseHandle", "Ptr", pipe[1])
DllCall("ConnectNamedPipe", "Ptr", pipe[2], "Ptr", 0)
if !(f := FileOpen(pipe[2], "h", cp))
return A_LastError
f.Write(script) ;// write dynamic code into pipe
f.Close(), DllCall("CloseHandle", "Ptr", pipe[2]) ;// close pipe
return exec
}
;=============================================================================
; Sample actions.ini file with 80 possible trigger colors listed
;
; var is to check for a variance in the color to trigger
; hotkey is the triggered hotkey
; zone will only let that hotkey trigger if it's in the X,Y "zone" or script # listed. 0 ignores
; should just need to modify RGB values and hotkey and a name if you want, rest can be left as is
;
;Name(color), RGB hex, var, hotkey, zone
;========================================================================
;action1(black), 0x000000, 0, !1, 0
;action2(dark gray 4), 0x434343, 0, +2, 0
;action3(dark gray 3), 0x666666, 0, 3, 0
;action4(dark gray 2), 0x999999, 0, 4, 0
;action5(dark gray 1), 0xB7B7B7, 0, 5, 0
;action6(gray), 0xCCCCCC, 0, 6, 0
;action7(light gray 1), 0xD9D9D9, 0, 7, 0
;action8(light gray 2), 0xEFEFEF, 0, 8, 0
;action9(light gray 3), 0xF3F3F3, 0, 9, 0
;action10(white), 0xFFFFFF, 0, 10, 0
;action11(red berry), 0x980000, 0, 11, 0
;action12(red), 0xFF0000, 0, 12, 0
;action13(orange), 0xFF9900, 0, 13, 0
;action14(yellow), 0xFFFF00, 0, 14, 0
;action15(green), 0x00FF00, 0, 15, 0
;action16(cyan), 0x00FFFF, 0, 16, 0
;action17(cornflower blue), 0x4A86E8, 0, 17, 0
;action18(blue), 0x0000FF, 0, 18, 0
;action19(purple), 0x9900FF, 0, 19, 0
;action20(magenta), 0xFF00FF, 0, 20, 0
;action21(light red berry 3), 0xE6B8AF, 0, 21, 0
;action22(light red 3), 0xF4CCCC, 0, 22, 0
;action23(light orange 3), 0xFCE5CD, 0, 23, 0
;action24(light yellow 3), 0xFFF2CC, 0, 24, 0
;action25(light green 3), 0xD9EAD3, 0, 25, 0
;action26(light cyan 3), 0xD0E0E3, 0, 26, 0
;action27(light cornflower blue 3), 0xC9DAF8, 0, 27, 0
;action28(light blue 3), 0xCFE2F3, 0, 28, 0
;action29(light purple 3), 0xD9D2E9, 0, 29, 0
;action30(light magenta 3), 0xEAD1DC, 0, 30, 0
;action31(light red berry 2), 0xDD7E6B, 0, 31, 0
;action32(light red 2), 0xEA9999, 0, 32, 0
;action33(light orange 2), 0xF9CB9C, 0, 33, 0
;action34(light yellow 2), 0xFFE599, 0, 34, 0
;action35(light green 2), 0xB6D7A8, 0, 35, 0
;action36(light cyan 2), 0xA2C4C9, 0, 36, 0
;action37(light cornflower blue 2), 0xA4C2F4, 0, 37, 0
;action38(light blue 2), 0x9FC5E8, 0, 38, 0
;action39(light purple 2), 0xB4A7D6, 0, 39, 0
;action40(light magenta 2), 0xD5A6BD, 0, 40, 0
;action41(light red berry 1), 0xCC4125, 0, 41, 0
;action42(light red 1), 0xE06666, 0, 42, 0
;action43(light orange 1), 0xF6B26B, 0, 43, 0
;action44(light yellow 1), 0xFFD966, 0, 44, 0
;action45(light green 1), 0x93C47D, 0, 45, 0
;action46(light cyan 1), 0x76A5AF, 0, 46, 0
;action47(light cornflower blue 1), 0x6D9EEB, 0, 47, 0
;action48(light blue 1), 0x6FA8DC, 0, 48, 0
;action49(light purple 1), 0x8E7CC3, 0, 49, 0
;action50(light magenta 1), 0xC27BA0, 0, 50, 0
;action51(dark red berry 1), 0xA61C00, 0, 51, 0
;action52(dark red 1), 0xCC0000, 0, 52, 0
;action53(dark orange 1), 0xE69138, 0, 53, 0
;action54(dark yellow 1), 0xF1C232, 0, 54, 0
;action55(dark green 1), 0x6AA84F, 0, 55, 0
;action56(dark cyan 1), 0x45818E, 0, 56, 0
;action57(dark cornflower blue 1), 0x3C78D8, 0, 57, 0
;action58(dark blue 1), 0x3D85C6, 0, 58, 0
;action59(dark purple 1), 0x674EA7, 0, 59, 0
;action60(dark magenta 1), 0xA64D79, 0, 60, 0
;action61(dark red berry 2), 0x85200C, 0, 61, 0
;action62(dark red 2), 0x990000, 0, 62, 0
;action63(dark orange 2), 0xB45F06, 0, 63, 0
;action64(dark yellow 2), 0xBF9000, 0, 64, 0
;action65(dark green 2), 0x38761D, 0, 65, 0
;action66(dark cyan 2), 0x134F5C, 0, 66, 0
;action67(dark cornflower blue 2), 0x1155CC, 0, 67, 0
;action68(dark blue 2), 0x0B5394, 0, 68, 0
;action69(dark purple 2), 0x351C75, 0, 69, 0
;action70(dark magenta 2), 0x741B47, 0, 70, 0
;action71(dark red berry 3), 0x5B0F00, 0, 71, 0
;action72(dark red 3), 0x660000, 0, 72, 0
;action73(dark orange 3), 0x783F04, 0, 73, 0
;action74(dark yellow 3), 0x7F6000, 0, 74, 0
;action75(dark green 3), 0x274E13, 0, 75, 0
;action76(dark cyan 3), 0x0C343D, 0, 76, 0
;action77(dark cornflower blue 3), 0x1C4587, 0, 77, 0
;action78(dark blue 3), 0x073763, 0, 78, 0
;action79(dark purple 3), 0x20124D, 0, 79, 0
;action80(dark magenta 3), 0x4C1130, 0, 80, 0