Jump to content

Recommended Posts

  • Moderators
Posted (edited)

Good evening,

Based on a number of posts I have found on this forum, I have been developing a script which permits the user to select a rectangle on the screen which is then captured for later use (OCR, image manipulation, etc). I have one remaining problem - when the user clicks the mouse for the first time to start the selection, there is an annoying "flash". From experimentation, I see it has to do with the creation of the $hRectangle_GUI window which momentarily blacks out the desktop - however, this GUI is required for the selected rectangle to be displayed, which makes it pretty essential to the whole endeavour! :-)

The following reduced script includes just the rectangle selection and screen capture functions:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <ScreenCapture.au3>
#Include <Misc.au3>

Global $iX1, $iY1, $iX2, $iY2, $aPos, $sMsg, $sBMP_Path

; Create GUI
$hMain_GUI = GUICreate("Select Rectangle", 240, 50)

$hRect_Button   = GUICtrlCreateButton("Mark Area",  10, 10, 80, 30)
$hCancel_Button = GUICtrlCreateButton("Cancel", 150, 10, 80, 30)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE, $hCancel_Button
            FileDelete(@ScriptDir & "\Rect.bmp")
            Exit
        Case $hRect_Button
            GUIDelete($hMain_GUI)
            Mark_Rect()
    ; Capture selected area
            $sBMP_Path = @ScriptDir & "\Rect.bmp"
            _ScreenCapture_Capture($sBMP_Path, $iX1, $iY1, $iX2, $iY2, False)
    ; Display image
            $hBitmap_GUI = GUICreate("Selected Rectangle", $iX2 - $iX1 + 1, $iY2 - $iY1 + 1, 100, 100)
            $hPic = GUICtrlCreatePic(@ScriptDir & "\Rect.bmp", 0, 0, $iX2 - $iX1 + 1, $iY2 - $iY1 + 1)
            GUISetState()
    EndSwitch

WEnd

; -------------

Func Mark_Rect()

    Local $aMouse_Pos, $aMask, $aM_Mask, $iTemp
    Local $UserDLL = DllOpen("user32.dll")

; Wait until mouse button pressed
    While Not _IsPressed("01", $UserDLL)
        Sleep(10)
    WEnd

; Get first mouse position
    $aMouse_Pos = MouseGetPos()
    $iX1 = $aMouse_Pos[0]
    $iY1 = $aMouse_Pos[1]

    Global $hRectangle_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST)
    GUISetBkColor(0x000000)
    GUISetState()

; Draw rectangle while mouse button pressed
    While _IsPressed("01", $UserDLL)

        $aMouse_Pos = MouseGetPos()

        $aM_Mask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", 0, "long", 0, "long", 0, "long", 0)
; Bottom of rectangle
        $aMask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", $iX1, "long", $aMouse_Pos[1], "long", $aMouse_Pos[0], "long", $aMouse_Pos[1] + 1)
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $aM_Mask[0], "long", $aMask[0], "long", $aM_Mask[0], "int", 2)
; Left of rectangle
        $aMask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", $iX1, "long", $iY1, "long", $iX1 + 1, "long", $aMouse_Pos[1])
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $aM_Mask[0], "long", $aMask[0], "long", $aM_Mask[0], "int", 2)
; Top of rectangle
        $aMask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", $iX1 + 1, "long", $iY1 + 1, "long", $aMouse_Pos[0], "long", $iY1)
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $aM_Mask[0], "long", $aMask[0], "long", $aM_Mask[0], "int", 2)
; Right of rectangle
        $aMask = DllCall("gdi32.dll", "long", "CreateRectRgn", "long", $aMouse_Pos[0], "long", $iY1, "long", $aMouse_Pos[0] + 1, "long", $aMouse_Pos[1])
        DllCall("gdi32.dll", "long", "CombineRgn", "long", $aM_Mask[0], "long", $aMask[0], "long", $aM_Mask[0], "int", 2)
        DllCall("user32.dll", "long", "SetWindowRgn", "hwnd", $hRectangle_GUI, "long", $aM_Mask[0], "int", 1)

        Sleep(50)

    WEnd

; Get second mouse position
    $iX2 = $aMouse_Pos[0]
    $iY2 = $aMouse_Pos[1]

; Set in correct order if required
    If $iX2 < $iX1 Then
        $iTemp = $iX1
        $iX1 = $iX2
        $iX2 = $iTemp
    EndIf
    If $iY2 < $iY1 Then
        $iTemp = $iY1
        $iY1 = $iY2
        $iY2 = $iTemp
    EndIf

    GUIDelete($hRectangle_GUI)
    DllClose($UserDLL)

EndFunc ;==>Mark_Rect

Thanks in advance for any suggestions or comments.

M23

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

Posted

put before your sleep(50) call in the while loop of your Mark_rect function this:

If BitAND(WinGetState(''), 2) <> 0 Then GUISetState()

and delete the ''GuiSetState()'' after the GuiSetBkColor()

  • Moderators
Posted (edited)

oMBRa,

Thanks for the solution.

The return value from WinGetState before the GUISetState call was 5 (exists, enabled). After the call it was 15 (exists, visible, enabled, active). So there are quite a few ways to check whether the call has been made.

M23

Edited after further investigation of the return values.

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

Posted

nice thread as iv just finished building my ClipCatch (with Screen Shot helper) pretty much doing the same thing when user uses "freehand mode" , i just used the _WinAPI_LineTo()

$squarepos = MouseGetPos()
            If $squareposx[2] <> $squarepos[0] Or $squareposx[3] <> $squarepos[1] Then
                $squareposx[2] = $squarepos[0]
                $squareposx[3] = $squarepos[1]
                _GDIPlus_GraphicsDrawImage($Hgraphicss, $Himage, 0, 0)
                _WinAPI_MoveTo($hDC, $squareposx[0], $squareposx[1])
                _WinAPI_LineTo($hDC, $squareposx[2], $squareposx[1])
                _WinAPI_LineTo($hDC, $squareposx[2], $squareposx[3])
                _WinAPI_LineTo($hDC, $squareposx[0], $squareposx[3])
                _WinAPI_LineTo($hDC, $squareposx[0], $squareposx[1])
            EndIf

after taking a screen shot of the whole screen onto a gui pasted over the desktop, stops peeps from dragging and pressing buttons when making there screen shot selection.

i spent a while looking at all the methods of doing the "rubber-band" selection square but didn't understand enough to use the methods you lot are using. but im guna have a look at what you lot have got and see what i can learn, i might even nick and use them if there smother than mine (if thats ok :) ) although what iv got is perfectly usable so i duno but all good stuff.

Thx all,Jack Dinn.

 

JD's Auto Internet Speed Tester

JD's Clip Catch (With Screen Shot Helper)

Projects :- AutoIt - My projects

My software never has bugs. It just develops random features. :-D

Posted (edited)

yea did try your script but found that it does just what i didn't want namely when you drag across text or click on a button/window it clicks, highlights or crashes it , just what i dont want but im sure i can just do what iv done with my clipcatch and do a screen shot first of whole window and put that over the desktop first. but nice little script though i might use.

thx.

Edited by JackDinn

Thx all,Jack Dinn.

 

JD's Auto Internet Speed Tester

JD's Clip Catch (With Screen Shot Helper)

Projects :- AutoIt - My projects

My software never has bugs. It just develops random features. :-D

  • Moderators
Posted (edited)

JackDinn,

Try this improved version that I have just this minute finalised. :-)

It should get over the 'selection' problem:

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <ScreenCapture.au3>
#Include <Misc.au3>

Global $iX1, $iY1, $iX2, $iY2, $aPos, $sMsg, $sBMP_Path

; Create GUI
$hMain_GUI = GUICreate("Select Rectangle", 240, 50)

$hRect_Button   = GUICtrlCreateButton("Mark Area",  10, 10, 80, 30)
$hCancel_Button = GUICtrlCreateButton("Cancel", 150, 10, 80, 30)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE, $hCancel_Button
            FileDelete(@ScriptDir & "\Rect.bmp")
            Exit
        Case $hRect_Button
            GUISetState(@SW_HIDE, $hMain_GUI)
            Mark_Rect()
        ; Capture selected area
            $sBMP_Path = @ScriptDir & "\Rect.bmp"
            _ScreenCapture_Capture($sBMP_Path, $iX1, $iY1, $iX2, $iY2, False)
            GUISetState(@SW_SHOW, $hMain_GUI)
        ; Display image
            $hBitmap_GUI = GUICreate("Selected Rectangle", $iX2 - $iX1 + 1, $iY2 - $iY1 + 1, 100, 100)
            $hPic = GUICtrlCreatePic(@ScriptDir & "\Rect.bmp", 0, 0, $iX2 - $iX1 + 1, $iY2 - $iY1 + 1)
            GUISetState()

    EndSwitch

WEnd

; -------------

Func Mark_Rect()

    Local $aMouse_Pos, $hMask, $hMaster_Mask, $iTemp
    Local $UserDLL = DllOpen("user32.dll")

; Create transparent GUI with Cross cursor
    $hCross_GUI = GUICreate("Test", @DesktopWidth, @DesktopHeight - 20, 0, 0, $WS_POPUP, $WS_EX_TOPMOST)
    WinSetTrans($hCross_GUI, "", 8)
    GUISetState(@SW_SHOW, $hCross_GUI)
    GUISetCursor(3, 1, $hCross_GUI)

    Global $hRectangle_GUI = GUICreate("", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST)
    GUISetBkColor(0x000000)

; Wait until mouse button pressed
    While Not _IsPressed("01", $UserDLL)
        Sleep(10)
    WEnd

; Get first mouse position
    $aMouse_Pos = MouseGetPos()
    $iX1 = $aMouse_Pos[0]
    $iY1 = $aMouse_Pos[1]

; Draw rectangle while mouse button pressed
    While _IsPressed("01", $UserDLL)

        $aMouse_Pos = MouseGetPos()

        $hMaster_Mask = _WinAPI_CreateRectRgn(0, 0, 0, 0)
        $hMask = _WinAPI_CreateRectRgn($iX1,  $aMouse_Pos[1], $aMouse_Pos[0],  $aMouse_Pos[1] + 1) ; Bottom of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($iX1, $iY1, $iX1 + 1, $aMouse_Pos[1]) ; Left of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($iX1 + 1, $iY1 + 1, $aMouse_Pos[0], $iY1) ; Top of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        $hMask = _WinAPI_CreateRectRgn($aMouse_Pos[0], $iY1, $aMouse_Pos[0] + 1,  $aMouse_Pos[1]) ; Right of rectangle
        _WinAPI_CombineRgn($hMaster_Mask, $hMask, $hMaster_Mask, 2)
        _WinAPI_DeleteObject($hMask)
        ; Set overall region
        _WinAPI_SetWindowRgn($hRectangle_GUI, $hMaster_Mask)

        If WinGetState($hRectangle_GUI) < 15 Then GUISetState()
        Sleep(10)

    WEnd

; Get second mouse position
    $iX2 = $aMouse_Pos[0]
    $iY2 = $aMouse_Pos[1]

; Set in correct order if required
    If $iX2 < $iX1 Then
        $iTemp = $iX1
        $iX1 = $iX2
        $iX2 = $iTemp
    EndIf
    If $iY2 < $iY1 Then
        $iTemp = $iY1
        $iY1 = $iY2
        $iY2 = $iTemp
    EndIf

    GUIDelete($hRectangle_GUI)
    GUIDelete($hCross_GUI)
    DllClose($UserDLL)

EndFunc  ;==>Mark_Rect

M23

Edit: Needed to delete combined masks to prevent memory leak

Edited by Melba23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

  Reveal hidden contents

 

Posted

yea n1 , you got it.

i didn't think of doing that , looks like you put a transparent GUI over the top so its sorts out that problem , i just was not sure if you could do a screen shot through a transparent gui, but looks like you can , well done.

Thx all,Jack Dinn.

 

JD's Auto Internet Speed Tester

JD's Clip Catch (With Screen Shot Helper)

Projects :- AutoIt - My projects

My software never has bugs. It just develops random features. :-D

Posted

many thx, iv managed to insert your method into my script with a little poking about as i use multi monitors, i was just wondering is there a way to get the mouse cursor to change to the cross without moving the mouse ? i would like it to change as soon as this screen shot method is chosen but as it is the cursor dont change until you move the mouse.

its not a major thing so im not to worried.

thx.

Thx all,Jack Dinn.

 

JD's Auto Internet Speed Tester

JD's Clip Catch (With Screen Shot Helper)

Projects :- AutoIt - My projects

My software never has bugs. It just develops random features. :-D

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
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...