Frostmouser

Screenshot tool, cancellation of the function.

8 posts in this topic

#1 ·  Posted (edited)

Hi everyone.

I'm trying to edit some sources from another person and after 4 hours of attempts i ran out of hope. :unsure:

Here is the code:

Func SHOOT()
    $fname = @MDAY & "-" & @MON & "-" & @YEAR & "_" & @HOUR & "." & @MIN & "." & @SEC
    If StringRight($DBOX_DIR, 1) <> "\" Then $DBOX_DIR=$DBOX_DIR&"\"
    Mark_Rect()
~
    TrayTip("Done!", $fullurl, 5, 1)
    ClipPut($fullurl)
EndFunc

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, 0, 0, $WS_POPUP, $WS_EX_TOOLWINDOW + $WS_EX_TOPMOST)
    WinSetTrans($hCross_GUI, "", 5)
    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)
    WinSetTrans($hRectangle_GUI, "", 50)

    ; 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,  $iY1, $aMouse_Pos[0],  $aMouse_Pos[1]) ; Bottom 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
There are 2 stages in the process of creating screenshot.
The first stage, when the hotkey that launches those functions is pressed. 
The second begins when the LMB is held down and user can select the area of the screen.
 
All i need is to be able to cancel this process at any stage with rightclick, ot at least in the first stage.
Edited by Frostmouser

Share this post


Link to post
Share on other sites



Frostmouser,

Welcome to the AutoIt forums. That function looks very familiar!

The only place where cancellation is simple is during the wait for the drawing of the rectangle - you just look for the right mouse button like this:

; Wait until mouse button pressed
While Not _IsPressed("01", $UserDLL)
    Sleep(10)
    If _IsPressed("02", $UserDLL) Then Return ; Cancel if right mouse button pressed <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
WEnd
Once the rectangle is being drawn you are past the point of no return.

However, in this similar script I provide rather more control over the process. You decide when to start the capture, can drag (white part) and resize (blue part) the area to scan, and then screen grab or cancel via a right-click context menu on the selected area:

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

Global $hCapture_GUI
; Set distance from edge of Capture_GUI where resizing is possible
Global Const $iMargin = 4
; Set max and min Capture_GUI sizes
Global Const $iGUIMinX = 50, $iGUIMinY = 50, $iGUIMaxX = @DesktopWidth - 100, $iGUIMaxY = @DesktopHeight - 100

_Main()

Func _Main()

    Local $sBMP_Path = @ScriptDir & "\Rect.bmp"

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

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

    GUISetState()

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE, $hCancel_Button
                FileDelete($sBMP_Path)
                Exit
            Case $hRect_Button
                GUISetState(@SW_HIDE, $hMain_GUI)
                Local $aCoords = Mark_Rect()
                ; Capture selected area
                _ScreenCapture_Capture($sBMP_Path, $aCoords[0], $aCoords[1], $aCoords[0] + $aCoords[2], $aCoords[1] + $aCoords[3], False)
                GUISetState(@SW_SHOW, $hMain_GUI)
                ; Display image
                Local $hBitmap_GUI = GUICreate("Selected Rectangle", $aCoords[2], $aCoords[3], 100, 100)
                Local $hPic = GUICtrlCreatePic(@ScriptDir & "\Rect.bmp", 0, 0, $aCoords[2], $aCoords[3])
                GUISetState()
        EndSwitch
    WEnd

EndFunc   ;==>_Main

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

Func Mark_Rect()

    ; Create capture GUI
    $hCapture_GUI = GUICreate("Y", 100, 100, -1, -1, $WS_POPUP, BitOR($WS_EX_LAYERED, $WS_EX_TOPMOST))
    GUISetBkColor(0xABCDEF)

    ; Create label for dragging
    Local $cLabel = GUICtrlCreateLabel("", $iMargin * 2, $iMargin * 2, 100 - ($iMargin * 4), 100 - ($iMargin * 4), -1, $GUI_WS_EX_PARENTDRAG)
    GUICtrlSetBkColor(-1, 0xFFFFFF)
    GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)

    ; Create context menu
    Local $cContextMenu = GUICtrlCreateContextMenu($cLabel)
    $cContext_Capture = GUICtrlCreateMenuItem("Capture", $cContextMenu)
    $cContext_Cancel = GUICtrlCreateMenuItem("Cancel", $cContextMenu)

    ; Hide GUI
    _WinAPI_SetLayeredWindowAttributes($hCapture_GUI, 0xABCDEF, 250)

    GUISetState()

    ; Set transparency level
    WinSetTrans($hCapture_GUI, "", 100)

    ; Register message handlers
    GUIRegisterMsg($WM_MOUSEMOVE, "_SetCursor") ; For cursor type change
    GUIRegisterMsg($WM_LBUTTONDOWN, "_WM_LBUTTONDOWN") ; For resize/drag
    GUIRegisterMsg($WM_GETMINMAXINFO, "_WM_GETMINMAXINFO") ; For GUI size limits

    While 1

        Switch GUIGetMsg()
            Case $cContext_Capture
                ; Get GUI position and delete
                $aPos = WinGetPos($hCapture_GUI)
                GUIDelete($hCapture_GUI)
                ; Unregister message handlers
                GUIRegisterMsg($WM_MOUSEMOVE, "")
                GUIRegisterMsg($WM_LBUTTONDOWN, "")
                GUIRegisterMsg($WM_GETMINMAXINFO, "")
                ; Peturn position
                Return $aPos
            Case $cContext_Cancel
                Exit
        EndSwitch
    WEnd

EndFunc   ;==>Mark_Rect

; Set cursor to correct resizing form if mouse is over a border
Func _SetCursor()
    Local $iCursorID
    Switch _Check_Border()
        Case 0
            $iCursorID = 2
        Case 1, 2
            $iCursorID = 13
        Case 3, 6
            $iCursorID = 11
        Case 5, 7
            $iCursorID = 10
        Case 4, 8
            $iCursorID = 12
    EndSwitch
    GUISetCursor($iCursorID, 1)
EndFunc   ;==>_SetCursor

; Check cursor type and resize/drag window as required
Func _WM_LBUTTONDOWN($hWnd, $iMsg, $wParam, $lParam)
    Local $iCursorType = _Check_Border()
    If $iCursorType > 0 Then ; Cursor is set to resizing style so send appropriate resize message
        $iResizeType = 0xF000 + $iCursorType
        _SendMessage($hCapture_GUI, $WM_SYSCOMMAND, $iResizeType, 0)
    EndIf
EndFunc   ;==>_WM_LBUTTONDOWN

; Determines if mouse cursor over a border
Func _Check_Border()
    Local $aCurInfo = GUIGetCursorInfo($hCapture_GUI)
    Local $aWinPos = WinGetPos($hCapture_GUI)
    Local $iSide = 0
    Local $iTopBot = 0
    If $aCurInfo[0] < $iMargin Then $iSide = 1
    If $aCurInfo[0] > $aWinPos[2] - $iMargin Then $iSide = 2
    If $aCurInfo[1] < $iMargin Then $iTopBot = 3
    If $aCurInfo[1] > $aWinPos[3] - $iMargin Then $iTopBot = 6
    Return $iSide + $iTopBot
EndFunc   ;==>_Check_Border

; Set min and max GUI sizes
Func _WM_GETMINMAXINFO($hWnd, $iMsg, $wParam, $lParam)
    $tMinMaxInfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam)
    DllStructSetData($tMinMaxInfo, 7, $iGUIMinX)
    DllStructSetData($tMinMaxInfo, 8, $iGUIMinY)
    DllStructSetData($tMinMaxInfo, 9, $iGUIMaxX)
    DllStructSetData($tMinMaxInfo, 10, $iGUIMaxY)
    Return 0
EndFunc   ;==>_WM_GETMINMAXINFO
I hope that proves useful. Please ask if I can be of any more help.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Thanks for the fast answer.

When i'm trying to cancel this process in the 1st stage it makes the copy of the last shot and not returning to the normal cursor.

It seems that the only way to get back to normal state is to close the program by using task manager.

Edited by Frostmouser

Share this post


Link to post
Share on other sites

Frostmouser,

Sorry, I did not really read my own code carefully enough. You also need to delete the 2 GUIs and close the DLL. Try this more comprehensive version:

; Wait until mouse button pressed
While Not _IsPressed("01", $UserDLL)
    Sleep(10)
    If _IsPressed("02", $UserDLL) Then
        GUIDelete($hRectangle_GUI)  ; Delete GUI
        GUIDelete($hCross_GUI)      ; Delete GUI
        DllClose($UserDLL)          ; Close DLL
        Return                      ; End Function
    EndIf
WEnd
That should solve the problem.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Yes, it works, but problem with duplicates is still there.

61L3mvk.png

Edited by Frostmouser

Share this post


Link to post
Share on other sites

Frostmouser,

Then we need to differentiate between a cancellation and a screenshot. So I suggest looking for a return value from the function like this:

Func SHOOT()
    $fname = @MDAY & "-" & @MON & "-" & @YEAR & "_" & @HOUR & "." & @MIN & "." & @SEC
    If StringRight($DBOX_DIR, 1) <> "\" Then $DBOX_DIR = $DBOX_DIR & "\"
    
    If Mark_Rect() = False Then Return ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
and setting the return value in the _Mark_Rect function like this:

; Wait until mouse button pressed
While Not _IsPressed("01", $UserDLL)
    Sleep(10)
    If _IsPressed("02", $UserDLL) Then
        GUIDelete($hRectangle_GUI)  ; Delete GUI
        GUIDelete($hCross_GUI)      ; Delete GUI
        DllClose($UserDLL)          ; Close DLL
        Return False                ; Cancel function and return False <<<<<<<<<<<<<<<<<<<<<
    EndIf
WEnd

[...]

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

    Return True                 ; Function ends and returns True <<<<<<<<<<<<<<<<<<<<<<<
EndFunc   ;==>Mark_Rect
Now the code will realise if the operation has been cancelled and not continue, which should solve the duplicate problem.

M23

1 person likes this

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Working perfectly now, thank you very much.

Share this post


Link to post
Share on other sites

Frostmouser,

Glad I could help - sorry it took a while to get it all fixed.

M23

1 person likes this

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

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