ScrCmp() is a MemCmp() done between pixels of two screen shots to detect any changes in a screen region.
ScrCmp() will wait for a pixel change and will return True on success.
To cancel the function's wait state, you may set the global array element A_Args.ScrCmp.Wait := False
Refer the following Global array elements to know the screen coordinates where the pixel change occurred:
Window X,Y : A_Args.ScrCmp.CX and A_Args.ScrCmp.CY
Screen X,Y : A_Args.ScrCmp.SX and A_Args.ScrCmp.SY
ScrCmp() will wait for a pixel change and will return True on success.
To cancel the function's wait state, you may set the global array element A_Args.ScrCmp.Wait := False
Refer the following Global array elements to know the screen coordinates where the pixel change occurred:
Window X,Y : A_Args.ScrCmp.CX and A_Args.ScrCmp.CY
Screen X,Y : A_Args.ScrCmp.SX and A_Args.ScrCmp.SY
How the function works?:
The function creates a Top-down bitmap measuring twice the height of the region to be monitored.
For eg., to monitor a screen area of 366x166, a 366x332 bitmap will be created.
The function takes a first screenshot for reference, at the bottom of the image stack.
Then within a loop, consecutive screen shots are done at the top of image stack.
For every screen shot, a binary compare is done between the top image and the reference (bottom) image
until any pixel change is detected
For eg., to monitor a screen area of 366x166, a 366x332 bitmap will be created.
The function takes a first screenshot for reference, at the bottom of the image stack.
Then within a loop, consecutive screen shots are done at the top of image stack.
For every screen shot, a binary compare is done between the top image and the reference (bottom) image
until any pixel change is detected
About Internal bitmap
Parameters:
- X, Y, W, H : Coordinates and dimension of region of screen unless Hwnd parameter is non-zero in which case the region belongs to client area of a window.
- Hwnd : Handle to a Window, Default value is 0x0
- Sleep1, Sleep2 : Default values are 100, 100
Sleep1 is duration (in ms) to wait between consecutive screen shots.
When a screen change is detected, an additional screen shot is taken to confirm that change didn't occur because of a flicker.
Sleep2 is duration (in ms) to wait between a regular screen shot and the additional confirmation screen shot.Example: ScrCmp(0, 0, 32, 32,, 60000, 200) will poll per minute.
When a screen change is detected, a confirmation screen shot is taken after a delay of 200ms.
For better readability, one may use ScrCmp(0, 0, 32, 32, 0x0, [60000,200]*) instead of ScrCmp(0, 0, 32, 32,, 60000, 200)
Usage example:
Code: Select all
#NoEnv
#Warn
#SingleInstance, Force
SetBatchLines, -1
ScrCmp(0, 0, 32, 32)
MsgBox Screen Region Change Detected!
; Paste ScrCmp() below
The function:
Code: Select all
ScrCmp( X, Y, W, H, Hwnd:=0x0, Sleep* ) { ; v0.66 By SKAN on D3B3/D3B6 @ tiny.cc/scrcmp
Local
Global A_Args
Sleep[1] := Sleep[1]="" ? 100 : Format("{:d}", Sleep[1])
Sleep[2] := Sleep[2]="" ? 100 : Format("{:d}", Sleep[2])
VarSetCapacity(BITMAPINFO, 40, 0)
NumPut(32, NumPut(1, NumPut(0-H*2, NumPut(W, NumPut(40,BITMAPINFO,"Int"),"Int"),"Int"),"Short"),"Short")
hBM := DllCall("Gdi32.dll\CreateDIBSection", "Ptr",0, "Ptr",&BITMAPINFO, "Int",0, "PtrP",pBits := 0, "Ptr",0, "Int",0, "Ptr")
sDC := DllCall("User32.dll\GetDC", "Ptr",(Hwnd := WinExist("ahk_id" . Hwnd)), "Ptr")
mDC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr",sDC, "Ptr")
DllCall("Gdi32.dll\SaveDC", "Ptr",mDC)
DllCall("Gdi32.dll\SelectObject", "Ptr",mDC, "Ptr",hBM)
DllCall("Gdi32.dll\BitBlt", "Ptr",mDC, "Int",0, "Int",H, "Int",W, "Int",H, "Ptr",sDC, "Int",X, "Int",Y, "Int",0x40CC0020)
A_Args.ScrCmp := {"Wait": 1}, Bytes := W*H*4, Count := 0
hMod := DllCall("Kernel32.dll\LoadLibrary", "Str","ntdll.dll", "Ptr")
While ( A_Args.ScrCmp.Wait && (Count<2) )
{
DllCall("Gdi32.dll\BitBlt", "Ptr",mDC, "Int",0, "Int",0, "Int",W, "Int",H, "Ptr",sDC, "Int",X, "Int",Y, "Int",0x40CC0020)
Count := ( (Byte := DllCall("ntdll.dll\RtlCompareMemory", "Ptr",pBits, "Ptr",pBits+Bytes, "Ptr",Bytes) ) != Bytes )
? (Count + 1) : 0
Sleep % (Count ? Sleep[2] : Sleep[1])
} Byte +=1
DllCall("Kernel32.dll\FreeLibrary", "Ptr",hMod)
SX := (CX := Mod((Byte-1)//4, W) + X), SY := (CY := (Byte-1) // (W*4) + Y)
If (Hwnd)
VarsetCapacity(POINT,8,0), NumPut(CX,POINT,"Int"), NumPut(CY,POINT,"Int")
, DllCall("User32.dll\ClientToScreen", "Ptr",Hwnd, "Ptr",&POINT)
, SX := NumGet(POINT,0,"Int"), SY := NumGet(POINT,4,"Int")
If (Wait := A_Args.ScrCmp.Wait)
A_Args.ScrCmp := { "Wait":0, "CX":CX, "CY":CY, "SX":SX, "SY":SY }
DllCall("Gdi32.dll\RestoreDC", "Ptr",mDC, "Int",-1)
DllCall("Gdi32.dll\DeleteDC", "Ptr",mDC)
DllCall("User32.dll\ReleaseDC", "Ptr",Hwnd, "Ptr",sDC)
DllCall("Gdi32.dll\DeleteObject", "Ptr",hBM)
Return ( !!Wait )
}