Sign in to follow this  
Followers 0
Grisgram

Checksum Utility with capture

3 posts in this topic

#1 ·  Posted (edited)

Hi,

I just wrote a little Utility in AutoIt which allows you to capture a screen region from a running application and get the PixelChecksum for that region so you can use the value later in your code to compare it.

Just start the script, enter the dimensions of the area to capture and click the "Capture" Button.

Then activate the window to capture and move the mouse to the point (top left corner) where you want to capture and press your hotkey.

The script will then capture that area, calculate the PixelChecksum and display it in a Textbox so you can copy it to your script.

The coordinates where you captured (in the client area of that window) will also be displayed.

I found it quite useful to automate some browser applications when it came to detect which kind of message or image is displayed in a specific area.

Here's the script, enjoy it and please let me know any enhancements you build into it or bugs you find.

cheers,

#include <GUIConstants.au3>
#include <ScreenCapture.au3>

Opt("GUIOnEventMode", 1); Change to OnEvent mode 
Opt("PixelCoordMode", 1); Screen coordinates
Opt("MouseCoordMode", 1); Screen coordinates


; -----------------------------------------------------------------------
; --- M A I N   P R O G R A M --- I N I T I A L I Z A T I O N
; -----------------------------------------------------------------------
; Create the main window
$mainwindow = GUICreate("AutoIt CheckSummer", 640, 400)
GUISetOnEvent($GUI_EVENT_CLOSE, "frm_Close")

; Create the picture box to hold the capture
GUICtrlCreateLabel("Captured image:", 240, 69)
$pic = GUICtrlCreateGraphic(240, 90, 256, 256)
GUICtrlSetBkColor($pic, 0xffffff)
GUICtrlCreateLabel("Captured image pixel checksum:", 240, 353)
$checksum = GUICtrlCreateEdit("0", 400, 350, 96, 20, $ES_NUMBER)

GUICtrlCreateLabel("Captured at mouse position:", 240, 370)
$capturepos = GUICtrlCreateLabel("                               ", 400, 370)

GUICtrlCreateLabel("This tool is used to capture a portion of an image and get the PixelChecksum for it.", 10, 10)
GUICtrlCreateLabel("Set the capture dimension in the textboxes then activate target window and move the mouse to the capture point.", 10, 24)
GUICtrlCreateLabel("The maximum image size to be captured for checksum is 256x256 pixels.", 10, 38)

GUICtrlCreateLabel("Width:", 10, 75)
GUICtrlCreateLabel("Height:", 10, 99)

$txtWidth = GUICtrlCreateEdit("32", 50, 72, 60, 20, $ES_NUMBER)
$txtHeight = GUICtrlCreateEdit("32", 50, 96, 60, 20, $ES_NUMBER)

$cmdCapture = GUICtrlCreateButton("Capture!", 35, 120, 90)
GUICtrlSetOnEvent($cmdCapture, "CaptureNow")

GUICtrlCreateLabel("Hotkey:", 10, 163)
$txtHotkey = GUICtrlCreateEdit("c", 50, 160, 60, 20)
GUICtrlCreateLabel("Press the hotkey when the mouse is", 10, 190)
GUICtrlCreateLabel("positioned at the capture point.", 10, 204)
GUICtrlCreateLabel("You can enter any custom hotkey here.", 10, 218)

GUICtrlCreateLabel("Modifier help:", 10, 240)
GUICtrlCreateLabel("^ ... Control", 10, 254)
GUICtrlCreateLabel("! ... Alt", 10, 268)
GUICtrlCreateLabel("+ ... Shift", 10, 282)
GUICtrlCreateLabel("# ... Windows key", 10, 296)

GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

$lastimg = 0

; Idle loop
While 1
  Sleep(1000)
WEnd

; -----------------------------------------------------------------------
; --- E V E N T   M E T H O D S - $mainwindow
; -----------------------------------------------------------------------
Func frm_Close()
    If @GUI_WINHANDLE = $mainwindow Then Exit
EndFunc


; -----------------------------------------------------------------------
; --- E V E N T   M E T H O D S - $cmdCapture
; -----------------------------------------------------------------------
Func CaptureNow()
    $wi = GUICtrlRead($txtWidth)
    $he = GUICtrlRead($txtHeight)

    if ($wi < 1 or $wi > 256 or $he < 1 or $he > 256) Then
        MsgBox(0, "Dimension error", "Width and Height must be between 1 and 256 (both including)!")
        Return
    EndIf

    HotKeySet(GUICtrlRead($txtHotkey), "CaptureKeyPressed")

EndFunc

Func CaptureKeyPressed()
    
    Opt("PixelCoordMode", 1); Screen coordinates
    Opt("MouseCoordMode", 1); Screen coordinates
    
    $mouse = MouseGetPos()
    $wi = GUICtrlRead($txtWidth)
    $he = GUICtrlRead($txtHeight)
    
    _ScreenCapture_Capture(@TempDir & "\capture.bmp", $mouse[0], $mouse[1], $mouse[0] + $wi, $mouse[1] + $he, False)

; Get the mouse pos where the capture happened (in the client area of the active form)
    Opt("PixelCoordMode", 2); Client area of active window
    Opt("MouseCoordMode", 2); Client area of active window
    $winmouse = MouseGetPos()

;Beep(1000, 50)
    Sleep(1000)
    
    WinActivate("AutoIt CheckSummer")
    WinWaitActive("AutoIt CheckSummer")
    GUICtrlSetData($capturepos, $winmouse[0] & " . " & $winmouse[1])
    if $lastimg <> 0 Then GUICtrlDelete($lastimg)
    $lastimg = GUICtrlCreatePic(@TempDir & "\capture.bmp", 240, 90, $wi, $he)
    GUICtrlSetData($checksum, PixelChecksum(240, 90, 240 + $wi - 1, 90 + $he - 1, 1))

EndFunc
Edited by Grisgram

Share this post


Link to post
Share on other sites



Great code.

I enhanced the tool in the following areas

* Added a small window with transparency that follows the cursor

* Added some hotkeys ctrl up,down, left, right to make the window capture area more relative from mouseposition to circumvent highlighting of buttons when you hover over them (actually then the color of the button changes)

* Added a find button with a straight forward search algorithm (slow but working). To test try something in upper corner of your screen not in the left bottom unless you have a long time available

** Optimizations have to be done to search within a window instead over whole desktop, combine with logic of pixelsearch to limit search area etc.

(search in forum on pixelsearch, getpixelcolor)

TO DO

* Hotkeys to change capture area instead of thru editbox to get exact right dimension easily

* Click or whatever when the area is found

** Easy for Powerbuilder unrecognizable objects

** Easy for difficult to recognize toolbars and other objects that are ownerdrawn

* Wrapper function for easier usage

* Check if its faster if first an in memory bitmap is made of the whole screen and use bitblt functions to identify corresponding area

(Reference: http://www.vbforums.com/showthread.php?t=474786)

* Combine with features from http://www.autoitscript.com/forum/index.ph...c=54776&hl=

#include <GUIConstants.au3>
#include <ScreenCapture.au3>

Opt("GUIOnEventMode", 1); Change to OnEvent mode 
Opt("PixelCoordMode", 1); Screen coordinates
Opt("MouseCoordMode", 1); Screen coordinates

; -----------------------------------------------------------------------
; --- M A I N   P R O G R A M --- I N I T I A L I Z A T I O N
; -----------------------------------------------------------------------
global $wi, $he, $deltaX, $deltaY;Made global as its shared by other functions
$deltax=1
$deltay=1

; Create the main window
$mainwindow = GUICreate("AutoIt CheckSummer", 640, 428)
GUISetOnEvent($GUI_EVENT_CLOSE, "frm_Close")

GUICtrlCreateLabel("This tool is used to capture a portion of an image and get the PixelChecksum for it.", 10, 10)
GUICtrlCreateLabel("Set the capture dimension in the textboxes then activate target window and move the mouse to the capture point.", 10, 24)
GUICtrlCreateLabel("The maximum image size to be captured for checksum is 256x256 pixels.", 10, 38)
GUICtrlCreateLabel("Ctrl up,down,left,right keys make the capturearea difference from mouse position so highlight of button is not captured.", 10, 52)

GUICtrlCreateLabel("Width:", 10, 75)
GUICtrlCreateLabel("Height:", 10, 99)

$txtWidth = GUICtrlCreateEdit("32", 50, 72, 60, 20, $ES_NUMBER)
$txtHeight = GUICtrlCreateEdit("32", 50, 96, 60, 20, $ES_NUMBER)

$cmdCapture = GUICtrlCreateButton("Capture!", 35, 120, 90)
GUICtrlSetOnEvent($cmdCapture, "CaptureNow")

$cmdFind = GUICtrlCreateButton("Find", 135, 120, 90)
GUICtrlSetOnEvent($cmdFind, "FindNow")

GUICtrlCreateLabel("Hotkey:", 10, 163) 
$txtHotkey = GUICtrlCreateEdit("c", 50, 160, 60, 20)
GUICtrlCreateLabel("Press the hotkey when the mouse is", 10, 190)
GUICtrlCreateLabel("positioned at the capture point.", 10, 204)
GUICtrlCreateLabel("You can enter any custom hotkey here.", 10, 218)

GUICtrlCreateLabel("Modifier help:", 10, 240)
GUICtrlCreateLabel("^ ... Control", 10, 254)
GUICtrlCreateLabel("! ... Alt", 10, 268)
GUICtrlCreateLabel("+ ... Shift", 10, 282)
GUICtrlCreateLabel("# ... Windows key", 10, 296)

; Create the picture box to hold the capture
GUICtrlCreateLabel("Captured image:", 240, 78)
$pic = GUICtrlCreateGraphic(240, 104, 256, 256)
GUICtrlSetBkColor($pic, 0xffffff)

GUICtrlCreateLabel("Captured image pixel checksum:", 240, 370)
$checksum = GUICtrlCreateEdit("0", 400, 370, 96, 20, $ES_NUMBER)

GUICtrlCreateLabel("Captured at mouse position:", 240, 394)
$capturepos = GUICtrlCreateLabel("                               ", 400, 394)


GUISwitch($mainwindow)
GUISetState(@SW_SHOW)

$lastimg = 0

HotKeySet("^{UP}", "onCtrlUp")
HotKeySet("^{DOWN}", "onCtrlDown")
HotKeySet("^{LEFT}", "onCtrlLeft")
HotKeySet("^{RIGHT}", "onCtrlRight")

func onCtrlUp()
    $deltaY=$deltaY+1
EndFunc
func onCtrlDown()
    $deltaY=$deltaY-1
EndFunc
func onCtrlRight()
    $deltaX=$deltaX-1
EndFunc
func onCtrlLeft()
    $deltaX=$deltaX+1
EndFunc

func setSnapWindow()
    Opt("PixelCoordMode", 1); Screen coordinates
    Opt("MouseCoordMode", 1); Screen coordinates
    
    $mouse = MouseGetPos()
;   winmove("Snaparea","", $mouse[0]+1,$mouse[1]+1)
    winmove("Snaparea","", $mouse[0]-$wi-$deltaX,$mouse[1]-$he-$deltaY)
EndFunc

$snapwindow = GuiCreate("Snaparea",32, 32,-1,-1, BitOR($WS_POPUP,$WS_BORDER), $WS_EX_TOPMOST)
WinSetTrans($snapWindow, "", 50)

; Idle loop
While 1
    Sleep(250)
    setSnapWindow()
WEnd

; -----------------------------------------------------------------------
; --- E V E N T   M E T H O D S - $mainwindow
; -----------------------------------------------------------------------
Func frm_Close()
    If @GUI_WINHANDLE = $mainwindow Then Exit
EndFunc

; -----------------------------------------------------------------------
; --- E V E N T   M E T H O D S - $cmdCapture
; -----------------------------------------------------------------------
Func CaptureNow()
    
    GUISwitch($mainwindow)
    $wi = GUICtrlRead($txtWidth)
    $he = GUICtrlRead($txtHeight)
    
    if ($wi < 1 or $wi > 256 or $he < 1 or $he > 256) Then
        MsgBox(0, "Dimension error", "Width and Height must be between 1 and 256 (both including)!")
        Return
    EndIf

; Show and receive the snaparea window
    $mouse = MouseGetPos()
    GUISetState(@SW_SHOW,$SnapWindow)
    winmove("Snaparea","", $mouse[0]-$wi-$deltaX,$mouse[1]-$he-$deltaY, $wi, $he)

    GUISwitch($mainwindow)
    HotKeySet(GUICtrlRead($txtHotkey), "CaptureKeyPressed")

EndFunc

Func CaptureKeyPressed()
    GUISetState(@SW_HIDE,$snapwindow)
    
    Opt("PixelCoordMode", 1); Screen coordinates
    Opt("MouseCoordMode", 1); Screen coordinates
    
    GUISwitch($mainwindow)
    $mouse = MouseGetPos()
    $wi = GUICtrlRead($txtWidth)
    $he = GUICtrlRead($txtHeight)
    
    _ScreenCapture_Capture(@TempDir & "\capture.bmp", $mouse[0] - $wi-$deltaX, $mouse[1]-$he-$deltaY, $mouse[0]-$deltaX, $mouse[1]-$deltaY, False)

; Get the mouse pos where the capture happened (in the client area of the active form)
    Opt("PixelCoordMode", 2); Client area of active window
    Opt("MouseCoordMode", 2); Client area of active window
    $winmouse = MouseGetPos()

;Beep(1000, 50)
;   Sleep(1000)
    
    WinActivate("AutoIt CheckSummer")
    WinWaitActive("AutoIt CheckSummer")
    GUICtrlSetData($capturepos, $winmouse[0] & " . " & $winmouse[1])
    if $lastimg <> 0 Then GUICtrlDelete($lastimg)
    $lastimg = GUICtrlCreatePic(@TempDir & "\capture.bmp", 240, 104, $wi, $he)
    GUICtrlSetData($checksum, PixelChecksum(240, 104, 240 + $wi - 1, 104 + $he - 1, 1))

    GUISetState(@SW_SHOW,$snapwindow)
EndFunc

func FindNow()
    $wi = GUICtrlRead($txtWidth)
    $he = GUICtrlRead($txtHeight)
    $tCheckSum=GUICtrlRead($checksum)
    FindCheckSumOnScreen($tCheckSum,$wi,$he)
EndFunc

func FindCheckSumOnScreen($checkSumOfImage,$iWidth, $iHeight)
    dim $screen_x=1, $screen_y=1
    $begin=TimerInit()
    Opt("PixelCoordMode", 1); Screen coordinates
    Opt("MouseCoordMode", 1); Screen coordinates
    for $screen_y=1 to @DesktopHeight
        for $screen_x=1 to @DesktopWidth
            $screenCheckSum=PixelChecksum($screen_x,$screen_y,$screen_x+$iWidth-1, $screen_y+$iHeight-1)
            if $screenCheckSum=$checkSumOfImage then 
                mousemove($screen_x,$screen_y,0)
                winmove("Snaparea","", $screen_x,$screen_y)
                msgbox(0,"Great","Found the picture at " & $screen_x & ":" &  $screen_y & "within " & timerdiff($begin) / 1000 & " seconds:")
                return
            EndIf
        Next
    next
EndFunc

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0