1. Fist you click Win+LMB(and hold lmb) and mark the area you want to be watched for changes and to be screenshoted
2. Then script detects pixel changes in that area and if any occur it screenshot previously selected window and save it to a folder
3. Folder is automatically created with the subfolder named after today's date
4. Every screenshot is counted and named afterwards
Stop script by pressing Ctrl+y
End script by clicking ESC
The script need gdip library to work
Script is REALLY sensitive, i've tried to crack the ScrCmp() to set % of pixel changed to return 'true' but im not that proficient in ahk.
So if anyone could help with that and point it to me or rewrite that part of the script? Or just have any idea how to do that?
Code: Select all
#NoEnv
#SingleInstance, Force
#Include Gdip.ahk
SetBatchLines, -1
CoordMode, Mouse, Screen
#LButton::
InputRect(vX1, vY1, vX2, vY2)
StopLoop := False
vW := vX2-vX1, vH := vY2-vY1
if (vInputRectState = -1)
return
Loop {
sleep, 200
ScrCmp(vX1, vY1, vW, vH)
FormatTime, dt_string,, yyyyMMdd
datei = C:\Users\%A_UserName%\Desktop\Screeny\%dt_string%
ifNotExist, %datei%
FileCreateDir, %datei%
; Read last filename.png - this will be the last one apha-numerically
MaxNum := "000"
Loop, %datei%\*.*
{ if(A_LoopFileName ~= "^SC")
&& (substr(A_LoopFileName,3,(A_LoopFileName ~= "\d+")) > MaxNum)
MaxNum := MaxNum := substr(A_LoopFileName,3,(A_LoopFileName ~= "\d+"))
}
MaxNum := printf("%03d",MaxNum + 1)
FileNam := "SC" . MaxNum . ".PNG" ; create new filename
datei .= "\"
datei .= FileNam
pToken := Gdip_Startup()
snap := Gdip_BitmapFromScreen(vX1 "|" vY1 "|" vW "|" vH)
Gdip_SaveBitmapToFile(snap, datei)
Gdip_DisposeImage(snap)
Gdip_Shutdown(pToken)
sleep, 200
if StopLoop
break
}
return
^y::
StopLoop := True
return
Esc:: ExitApp
;==================================================
;thx jeeswg
;https://www.autohotkey.com/boards/viewtopic.php?t=42810
;based on LetUserSelectRect by Lexikos:
;LetUserSelectRect - select a portion of the screen - Scripts and Functions - AutoHotkey Community
;https://autohotkey.com/board/topic/45921-letuserselectrect-select-a-portion-of-the-screen/
;note: 'CoordMode, Mouse, Screen' must be used in the auto-execute section
;e.g.
;InputRect(vWinX, vWinY, vWinR, vWinB)
;vWinW := vWinR-vWinX, vWinH := vWinB-vWinY
;if (vInputRectState = -1)
; return
InputRect(ByRef vX1, ByRef vY1, ByRef vX2, ByRef vY2)
{
global vInputRectState := 0
DetectHiddenWindows, On
Gui, 1: -Caption +ToolWindow +AlwaysOnTop +hWndhGuiSel
Gui, 1: Color, Red
WinSet, Transparent, 128, % "ahk_id " hGuiSel
Hotkey, *LButton, InputRect_Return, On
Hotkey, *RButton, InputRect_End, On
Hotkey, Esc, InputRect_End, On
KeyWait, LButton, D
MouseGetPos, vX0, vY0
SetTimer, InputRect_Update, 10
KeyWait, LButton
Hotkey, *LButton, Off
Hotkey, Esc, InputRect_End, Off
SetTimer, InputRect_Update, Off
Gui, 1: Destroy
return
InputRect_Update:
if !vInputRectState
{
MouseGetPos, vX, vY
(vX < vX0) ? (vX1 := vX, vX2 := vX0) : (vX1 := vX0, vX2 := vX)
(vY < vY0) ? (vY1 := vY, vY2 := vY0) : (vY1 := vY0, vY2 := vY)
Gui, 1:Show, % "NA x" vX1 " y" vY1 " w" (vX2-vX1) " h" (vY2-vY1)
return
}
vInputRectState := 1
InputRect_End:
if !vInputRectState
vInputRectState := -1
Hotkey, *LButton, Off
Hotkey, *RButton, Off
Hotkey, Esc, Off
SetTimer, InputRect_Update, Off
Gui, 1: Destroy
InputRect_Return:
return
}
;==================================================
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 )
}
printf(string, prms*) ; uses variadics to handle variable number of inputs
{ listlines, off
padchar := " "
for each, prm in prms
{ RegExMatch(string,"`%(.*?)([s|f|d])",m) ; regular expression search
format := m1
stringleft, Pad, format, 1
if(Pad = "0")
padchar := "0"
type := m2
if (type = "f") ; format float using setformat command
{ originalformat := A_FormatFloat
SetFormat, Float, %format%
prm += 0.0
SetFormat, Float, %originalformat%
}
else if (type = "s") ; format string (pad string if necessary, negative number indicates right justify)
{ if (format < 0)
loop % -format-StrLen(prm)
prm := padchar prm
else
loop % format-StrLen(prm)
prm := prm padchar
}
else if(type = "d")
{ originalformat := A_FormatInteger
SetFormat, Integer, %format%
Str =
loop % abs(format)-StrLen(prm) ; %
str .= padchar
if(format < 0)
prm .= str
else
prm := str prm
SetFormat, Integer, %originalformat%
}
else
msgbox, unknown type = %type% specified in call to printf
StringReplace, string, string, % "`" m, % prm ; "%" symbol must be escaped with backtick
}
listlines, on
return string
}