Запускает, если не запущен, Paint и находит координаты первого коричневого пикселя (в палитре Paint), после чего поиск прекращается.
Поиск идет слева-направо, сверху вниз. По умолчанию, поиск ведется по всей клиентской части окна, если будете ограничивать область, координаты x1 x2 y1 y2 задавайте тоже клиентские.
Координаты найденного пикселя будут оконные.
SetBatchLines -1
classApp := "ahk_class MSPaintApp", exeApp := "mspaint.exe"
classApp := "ahk_class MSPaintApp", exeApp := "mspaint.exe"
IfWinNotExist % classApp
{
Run % exeApp
Sleep 1000
}
hwnd := WinExist(classApp)
; делаем снимок
hMemDC := WindowBitmap_Capture(hwnd, hDC, hBitmap)
; находим пиксели
WinP := WinGetP(hwnd)
start:=A_TickCount
Brown:=0x577AB9
pix := WindowBitmap_SearchFirstPixel(hMemDC, Brown, WinP)
; col := WindowBitmap_PixelGetColor(hMemDC, x, y)
; MsgBox % (col = -1) ? "Error" : Format("{:#08x}",col)
period:=A_TickCount-start
; очищаем память
WindowBitmap_Delete(hWnd, hDC, hBitmap)
MsgBox % "Pixel " Brown (IsObject(pix) ? " found on " pix.x "x " pix.y "y" : " not found") " | " period "ms "
WinActivate ahk_id %hwnd%
MouseMove pix.x, pix.y
Return
WindowBitmap_PixelGetColor(hMemDC, x, y) {
Return DllCall("GetPixel", Ptr, hMemDC, UInt, x, UInt, y)
}
WindowBitmap_Capture(hWnd, ByRef hDC, ByRef hBitmap) {
WinGetPos,,, Width, Height, ahk_id %hWnd%
hDC := DllCall("GetDC", Ptr, hWnd, Ptr)
hMemDC := DllCall("CreateCompatibleDC", Ptr, hDC)
hBitmap := DllCall("CreateCompatibleBitmap", Ptr, hDC, Int, Width, Int, Height, Ptr)
DllCall("SelectObject", Ptr, hMemDC, Ptr, hBitmap)
DllCall("PrintWindow", Ptr, hWnd, Ptr, hMemDC, UInt, 0) ; 0-50 ms depend on window size; GetPixel - 0.004 ms on each ( > 8sec on FullHD display capture)
Return hMemDC
}
WindowBitmap_Delete(hWnd, ByRef hDC, ByRef hBitmap) {
DllCall("DeleteObject", Ptr, hBitmap)
DllCall("DeleteDC", Ptr, hMemDC)
DllCall("ReleaseDC", Ptr, hWnd, Ptr, hDC)
}
WindowBitmap_SearchFirstPixel(hDC, searchColorBGR, WinP, x1:=0, y1:=0, x2:="", y2:="") {
x1+=WinP.Client2Win.x, y1+=WinP.Client2Win.y
x2 := x2 ? x2 : WinP.Client2Win.x + WinP.Client.w
y2 := y2 ? y2 : WinP.Client2Win.y + WinP.Client.h
y:=y1
While (++y<y2)
{
x:=x1
While (++x<x2)
{
colorBGR := DllCall("GetPixel", "UInt", hDC, "Int", x, "Int", y, "UInt")
; OutputDebug % "[" Format("{:03}",x) "," Format("{:03}",y) "]: " Format("{:#08x}",colorBGR)
if (colorBGR = searchColorBGR) {
Return {x:x, y:y}
}
}
}
Return false
}
WinGetP(hwnd) {
WinGetPos, xWin, yWin, wWin, hWin, ahk_id %hWnd%
VarSetCapacity(pt, 16)
NumPut(x, pt, 0) || NumPut(y, pt, 4) || NumPut(w, pt, 8) || NumPut(h, pt, 12)
if (!DllCall("GetClientRect", "uint", hwnd, "uint", &pt))
|| (!DllCall("ClientToScreen", "uint", hwnd, "uint", &pt))
Return
x := NumGet(pt, 0, "int"), y := NumGet(pt, 4, "int")
w := NumGet(pt, 8, "int"), h := NumGet(pt, 12, "int")
Client := {x:x, y:y, w:w, h:h}, Client2Win := {x:x-xWin, y:y-yWin, w:w, h:h}
Return {x:xWin, y:yWin, w:wWin, h:hWin, Client2Win:Client2Win, Client:Client}
}
У меня 8 пикселей сверху не соответсвуют реальным, а также все неклиентские пиксели (поэтому и ограничил поиск).
Также к недостаткам отнесу время работы вызываемой из Dll ф-ии GetPixel - 0.004 мс, что для FullHD дисплея выливается в 8 секунд, если окно развернуто на весь экран, и ф-ия поиска проходит до конца, не найдя пикселя.
Забавно, что в некоторых случаях белый холст Painta сей метод видит черным (что можно увидеть также в AhkSpy от serzh42saratov).
Если сделать ассемблерную вставку, то прошерстить экран можно за доли секунды, просто пока никто не заморочился сделать это.