Snipping Tool automation

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
roysubs
Posts: 421
Joined: 29 Sep 2018, 16:37

Snipping Tool automation

11 Feb 2021, 13:03

I have a question on completing all of the screen capture tasks that I do on a regular basis, and I see that this is all now possible with built in Windows tools (so no need for any third-party tools at all from what I can see, and I prefer that, why install stuff when AutoHotkey can do everything!)

I literally only do precisely three things with screen shots, as follows:

1. Full screen screenshot into a file. This is fully answered in this thread. This is perfect and does exactly what I need. https://www.autohotkey.com/boards/viewtopic.php?f=76&t=86780

2. Snipping Tool > Rectangle snip, i.e. pull up the crosshair, define a region to snip.

3. Snipping Tool > Window snip, i.e. move the mouse over a Window and snip that precise Window area and nothing else.

However, there is a problem with 2 or 3 in that I cannot automate them as yet. The problems are that I can't just call them directly, I have to fumble open the Snipping Tool and then I have to save the file after taking a snip etc.

Does someone have a solution for 2. and 3. above such that I would be able to do the following:

• Ctrl-PrintScreen will do 2, i.e. pull up the crosshairs, then I select a region, then that snip is saved to a file and then Snipping Tool is closed (or minimised)

• Ctrl-WinKey-PrintScreen will do 3, i.e. go into Window capture mode from Snipping Tool so that I can move a mouse over a window and click it and that Window is saved into a file and then Snipping Tool is closed (or minimised).

There's really no more that I would ever need from taking screen shots, and I do these tasks dozens of times a day (sometimes hundreds of times if I am documenting something for work etc) - so having these straight from AutoHotkey would be amazingly useful. :)


Do you think
User avatar
Smile_
Posts: 857
Joined: 03 May 2020, 00:51

Re: Snipping Tool automation

11 Feb 2021, 15:38

Without using Snipping Tool:
1 - Selecting an area will take screenshot for it.
2 - Pressing Control + Win + PrintScreen will auto take screenshot for the activated window.

Code: Select all

~LButton::
    MouseGetPos, Xi, Yi
Return

~LButton up::
    MouseGetPos, Xf, Yf
    If (Xi < Xf) && (Yi < Yf)
        CaptureScreen(Xi ", " Yi ", " Xf ", " Yf,, A_Desktop "\" A_Now ".png")
    Else If (Xi > Xf) && (Yi > Yf)
        CaptureScreen(Xf ", " Yf ", " Xi ", " Yi,, A_Desktop "\" A_Now ".png")
Return

^#printscreen::
    WinGetTitle, Title, A
    WinGetPos, X, Y, Width, Height, %Title%
    Width += X, Height += Y
    CaptureScreen(X ", " Y ", " Width ", " Height,, A_Desktop "\" A_Now ".png")
Return

;=================== CaptureScreen.ahk from LinearSpoon 20150220 ==================
;-https://autohotkey.com/board/topic/121619-screencaptureahk-broken-capturescreen-function-win-81-x64/
/* CaptureScreen(aRect, bCursor, sFileTo, nQuality)
1) If the optional parameter bCursor is True, captures the cursor too.
2) If the optional parameter sFileTo is 0, set the image to Clipboard.
   If it is omitted or "", saves to screen.bmp in the script folder,
   otherwise to sFileTo which can be BMP/JPG/PNG/GIF/TIF.
3) The optional parameter nQuality is applicable only when sFileTo is JPG. Set it to the desired quality level of the resulting JPG, an integer between 0 - 100.
4) If aRect is 0/1/2/3, captures the entire desktop/active window/active client area/active monitor.
5) aRect can be comma delimited sequence of coordinates, e.g., "Left, Top, Right, Bottom" or "Left, Top, Right, Bottom, Width_Zoomed, Height_Zoomed".
   In this case, only that portion of the rectangle will be captured. Additionally, in the latter case, zoomed to the new width/height, Width_Zoomed/Height_Zoomed.

Example:
CaptureScreen(0)
CaptureScreen(1)
CaptureScreen(2)
CaptureScreen(3)
CaptureScreen("100, 100, 200, 200")
CaptureScreen("100, 100, 200, 200, 400, 400")   ; Zoomed
*/

/* Convert(sFileFr, sFileTo, nQuality)
Convert("C:\image.bmp", "C:\image.jpg")
Convert("C:\image.bmp", "C:\image.jpg", 95)
Convert(0, "C:\clip.png")   ; Save the bitmap in the clipboard to sFileTo if sFileFr is "" or 0.
*/

;--------------------------------------------------------------------
CaptureScreen(aRect = 0, bCursor = False, sFile = "", nQuality = "")
{
    If !aRect
    {
        SysGet, nL, 76 ; virtual screen left & top
        SysGet, nT, 77
        SysGet, nW, 78	; virtual screen width and height
        SysGet, nH, 79
    }
    Else If aRect = 1
        WinGetPos, nL, nT, nW, nH, A
    Else If aRect = 2
    {
        WinGet, hWnd, ID, A
        VarSetCapacity(rt, 16, 0)
        DllCall("GetClientRect" , "ptr", hWnd, "ptr", &rt)
        DllCall("ClientToScreen", "ptr", hWnd, "ptr", &rt)
        nL := NumGet(rt, 0, "int")
        nT := NumGet(rt, 4, "int")
        nW := NumGet(rt, 8)
        nH := NumGet(rt,12)
    }
    Else If aRect = 3
    {
        VarSetCapacity(mi, 40, 0)
        DllCall("GetCursorPos", "int64P", pt), NumPut(40,mi,0,"uint")
        DllCall("GetMonitorInfo", "ptr", DllCall("MonitorFromPoint", "int64", pt, "Uint", 2, "ptr"), "ptr", &mi)
        nL := NumGet(mi, 4, "int")
        nT := NumGet(mi, 8, "int")
        nW := NumGet(mi,12, "int") - nL
        nH := NumGet(mi,16, "int") - nT
    }
    Else
    {
        StringSplit, rt, aRect, `,, %A_Space%%A_Tab%
        nL := rt1	; convert the Left,top, right, bottom into left, top, width, height
        nT := rt2
        nW := rt3 - rt1
        nH := rt4 - rt2
        znW := rt5
        znH := rt6
    }

    mDC := DllCall("CreateCompatibleDC", "ptr", 0, "ptr")
    hBM := CreateDIBSection(mDC, nW, nH)
    oBM := DllCall("SelectObject", "ptr", mDC, "ptr", hBM, "ptr")
    hDC := DllCall("GetDC", "ptr", 0, "ptr")
    DllCall("BitBlt", "ptr", mDC, "int", 0, "int", 0, "int", nW, "int", nH, "ptr", hDC, "int", nL, "int", nT, "Uint", 0x40CC0020)
    DllCall("ReleaseDC", "ptr", 0, "ptr", hDC)
    If bCursor
        CaptureCursor(mDC, nL, nT)
    DllCall("SelectObject", "ptr", mDC, "ptr", oBM)
    DllCall("DeleteDC", "ptr", mDC)
    If znW && znH
        hBM := Zoomer(hBM, nW, nH, znW, znH)
    If sFile = 0
        SetClipboardData(hBM)
    Else Convert(hBM, sFile, nQuality), DllCall("DeleteObject", "ptr", hBM)
    }

CaptureCursor(hDC, nL, nT)
{
    VarSetCapacity(mi, 32, 0), Numput(16+A_PtrSize, mi, 0, "uint")
    DllCall("GetCursorInfo", "ptr", &mi)
    bShow := NumGet(mi, 4, "uint")
    hCursor := NumGet(mi, 8)
    xCursor := NumGet(mi,8+A_PtrSize, "int")
    yCursor := NumGet(mi,12+A_PtrSize, "int")

    DllCall("GetIconInfo", "ptr", hCursor, "ptr", &mi)
    xHotspot := NumGet(mi, 4, "uint")
    yHotspot := NumGet(mi, 8, "uint")
    hBMMask := NumGet(mi,8+A_PtrSize)
    hBMColor := NumGet(mi,16+A_PtrSize)

    If bShow
        DllCall("DrawIcon", "ptr", hDC, "int", xCursor - xHotspot - nL, "int", yCursor - yHotspot - nT, "ptr", hCursor)
    If hBMMask
        DllCall("DeleteObject", "ptr", hBMMask)
    If hBMColor
        DllCall("DeleteObject", "ptr", hBMColor)
}

Zoomer(hBM, nW, nH, znW, znH)
{
    mDC1 := DllCall("CreateCompatibleDC", "ptr", 0, "ptr")
    mDC2 := DllCall("CreateCompatibleDC", "ptr", 0, "ptr")
    zhBM := CreateDIBSection(mDC2, znW, znH)
    oBM1 := DllCall("SelectObject", "ptr", mDC1, "ptr", hBM, "ptr")
    oBM2 := DllCall("SelectObject", "ptr", mDC2, "ptr", zhBM, "ptr")
    DllCall("SetStretchBltMode", "ptr", mDC2, "int", 4)
    DllCall("StretchBlt", "ptr", mDC2, "int", 0, "int", 0, "int", znW, "int", znH, "ptr", mDC1, "int", 0, "int", 0, "int", nW, "int", nH, "Uint", 0x00CC0020)
    DllCall("SelectObject", "ptr", mDC1, "ptr", oBM1)
    DllCall("SelectObject", "ptr", mDC2, "ptr", oBM2)
    DllCall("DeleteDC", "ptr", mDC1)
    DllCall("DeleteDC", "ptr", mDC2)
    DllCall("DeleteObject", "ptr", hBM)
Return zhBM
}

Convert(sFileFr = "", sFileTo = "", nQuality = "")
{
    If (sFileTo = "")
        sFileTo := A_ScriptDir . "\screen.bmp"
    SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo

    If Not hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll", "ptr")
        Return	sFileFr+0 ? SaveHBITMAPToFile(sFileFr, sDirTo (sDirTo = "" ? "" : "\") sNameTo ".bmp") : ""
        VarSetCapacity(si, 16, 0), si := Chr(1)
        DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "ptr", &si, "ptr", 0)

        If !sFileFr
        {
            DllCall("OpenClipboard", "ptr", 0)
            If	(DllCall("IsClipboardFormatAvailable", "Uint", 2) && (hBM:=DllCall("GetClipboardData", "Uint", 2, "ptr")))
                DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "ptr", hBM, "ptr", 0, "ptr*", pImage)
            DllCall("CloseClipboard")
        }
        Else If	sFileFr Is Integer
            DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "ptr", sFileFr, "ptr", 0, "ptr*", pImage)
        Else	DllCall("gdiplus\GdipLoadImageFromFile", "wstr", sFileFr, "ptr*", pImage)
            DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
        VarSetCapacity(ci,nSize,0)
        DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "ptr", &ci)
        struct_size := 48+7*A_PtrSize, offset := 32 + 3*A_PtrSize, pCodec := &ci - struct_size
        Loop, %	nCount
            If InStr(StrGet(Numget(offset + (pCodec+=struct_size)), "utf-16") , "." . sExtTo)
            break

        If (InStr(".JPG.JPEG.JPE.JFIF", "." . sExtTo) && nQuality<>"" && pImage && pCodec < &ci + nSize)
        {
            DllCall("gdiplus\GdipGetEncoderParameterListSize", "ptr", pImage, "ptr", pCodec, "UintP", nCount)
            VarSetCapacity(pi,nCount,0), struct_size := 24 + A_PtrSize
            DllCall("gdiplus\GdipGetEncoderParameterList", "ptr", pImage, "ptr", pCodec, "Uint", nCount, "ptr", &pi)
            Loop, %	NumGet(pi,0,"uint")
                If (NumGet(pi,struct_size*(A_Index-1)+16+A_PtrSize,"uint")=1 && NumGet(pi,struct_size*(A_Index-1)+20+A_PtrSize,"uint")=6)
            {
                pParam := &pi+struct_size*(A_Index-1)
                NumPut(nQuality,NumGet(NumPut(4,NumPut(1,pParam+0,"uint")+16+A_PtrSize,"uint")),"uint")
                Break
            }
        }

        If pImage
            pCodec < &ci + nSize	? DllCall("gdiplus\GdipSaveImageToFile", "ptr", pImage, "wstr", sFileTo, "ptr", pCodec, "ptr", pParam) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pImage, "ptr*", hBitmap, "Uint", 0) . SetClipboardData(hBitmap), DllCall("gdiplus\GdipDisposeImage", "ptr", pImage)

        DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
        DllCall("FreeLibrary", "ptr", hGdiPlus)
    }

    CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
    {
        VarSetCapacity(bi, 40, 0)
        NumPut(40, bi, "uint")
        NumPut(nW, bi, 4, "int")
        NumPut(nH, bi, 8, "int")
        NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
    Return DllCall("gdi32\CreateDIBSection", "ptr", hDC, "ptr", &bi, "Uint", 0, "UintP", pBits, "ptr", 0, "Uint", 0, "ptr")
}

SaveHBITMAPToFile(hBitmap, sFile)
{
    VarSetCapacity(oi,104,0)
    DllCall("GetObject", "ptr", hBitmap, "int", 64+5*A_PtrSize, "ptr", &oi)
    fObj := FileOpen(sFile, "w")
    fObj.WriteShort(0x4D42)
    fObj.WriteInt(54+NumGet(oi,36+2*A_PtrSize,"uint"))
    fObj.WriteInt64(54<<32)
    fObj.RawWrite(&oi + 16 + 2*A_PtrSize, 40)
    fObj.RawWrite(NumGet(oi, 16+A_PtrSize), NumGet(oi,36+2*A_PtrSize,"uint"))
    fObj.Close()
}

SetClipboardData(hBitmap)
{
    VarSetCapacity(oi,104,0)
    DllCall("GetObject", "ptr", hBitmap, "int", 64+5*A_PtrSize, "ptr", &oi)
    sz := NumGet(oi,36+2*A_PtrSize,"uint")
    hDIB :=	DllCall("GlobalAlloc", "Uint", 2, "Uptr", 40+sz, "ptr")
    pDIB := DllCall("GlobalLock", "ptr", hDIB, "ptr")
    DllCall("RtlMoveMemory", "ptr", pDIB, "ptr", &oi + 16 + 2*A_PtrSize, "Uptr", 40)
    DllCall("RtlMoveMemory", "ptr", pDIB+40, "ptr", NumGet(oi, 16+A_PtrSize), "Uptr", sz)
    DllCall("GlobalUnlock", "ptr", hDIB)
    DllCall("DeleteObject", "ptr", hBitmap)
    DllCall("OpenClipboard", "ptr", 0)
    DllCall("EmptyClipboard")
    DllCall("SetClipboardData", "Uint", 8, "ptr", hDIB)
    DllCall("CloseClipboard")
}
;============================================= END SCRIPT ===================================
User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: Snipping Tool automation

11 Feb 2021, 20:53

roysubs wrote:
11 Feb 2021, 13:03
2. Snipping Tool > Rectangle snip, i.e. pull up the crosshair, define a region to snip.
You can use this to create your crosshairs and to define the region to snip.

Code: Select all

;*****************************************************************
;#Include <TargetArea>   ;https://www.autohotkey.com/boards/viewtopic.php?f=6&t=85494
;*****************************************************************
#SingleInstance, Force
SetBatchLines, -1
return

^PrintScreen::
	KeyWait, ctrl
	if(Positions := TargetArea.Set())
		msgbox,% "X1: " Positions.X1 "`nY1: " Positions.Y1 "`nX2: " Positions.X2 "`nY2: " Positions.Y2 "`nW: " Positions.W "`nH: " Positions.H
	else
		msgbox, Operation Canceled
	return

*ESC::ExitApp


;***********************************************************************************************************************************************
;***********************************************************************************************************************************************
;TargetArea Class By: Hellbent
; Jan 7th, 2021
; Select and show a rectangular zone on your screen (returns a object with X1, X2, Y1, Y2, W, H Keys)
; Credits: 
;***********************************************************************************************************************************************
;***********************************************************************************************************************************************
class TargetArea	{
	Set(color:="00FF00"){
		This.Color := color
		This.MonitorBounds := []
		This._CreateWindows()
		return This._SetPositions()
	}_CreateWindows(){
		local Hwnd, bd, tx, ty, Cmon
		CoordMode, Mouse, Screen
		MouseGetPos, tx, ty
		This.Name := [], This.Cross := []
		Gui, HBBackgroundGuiHB:New,  +AlwaysOnTop -Caption -DPIScale +ToolWindow +LastFound
		Gui, HBBackgroundGuiHB:Color,% This.Color
		WinSet, Transparent, 100
		Loop, % This._GetMonitorCount()	{
			This.Name[A_Index] := "HBSearchAreaWindowHB_" A_Index
			This.Cross[A_Index] := {}
			This.MonitorBounds[A_Index] := This._GetMonitorBounds(A_Index)
			Gui, % This.Name[A_Index] ":New", +AlwaysOnTop -Caption -DPIScale +ToolWindow +LastFound 
			WinSet, TransColor, 123456
			Gui, % This.Name[A_Index] ":Color", 123456
			Gui, % This.Name[A_Index] ":Margin", 0, 0
			Gui, % This.Name[A_Index] ":Add", Progress, % "x0 y" ty-This.MonitorBounds[A_Index].Y1  " w" This.MonitorBounds[A_Index].X2 - This.MonitorBounds[A_Index].X1 " h1 hwndhwnd BackgroundBlack cBlack Disabled", 100
			This.Cross[A_Index].Horz1 := hwnd
			Gui, % This.Name[A_Index] ":Add", Progress, x0 y0 w0 h0 hwndhwnd BackgroundBlack cBlack Disabled, 100
			This.Cross[A_Index].Horz2 := hwnd
			Gui, % This.Name[A_Index] ":Add", Progress, % "x" tx - This.MonitorBounds[A_Index].X1 " y0 w1 h" This.MonitorBounds[A_Index].Y2 - This.MonitorBounds[A_Index].Y1 " hwndhwnd BackgroundBlack cBlack Disabled", 100
			This.Cross[A_Index].Vert1 := hwnd
			Gui, % This.Name[A_Index] ":Add", Progress, x0 y0 w0 h0 hwndhwnd BackgroundBlack cBlack Disabled, 100
			This.Cross[A_Index].Vert2 := hwnd
			Gui, % This.Name[A_Index] ":Show", % "x" This.MonitorBounds[A_Index].X1 " y" This.MonitorBounds[A_Index].Y1 " w" This.MonitorBounds[A_Index].X2 - This.MonitorBounds[A_Index].X1 " h" This.MonitorBounds[A_Index].Y2 - This.MonitorBounds[A_Index].Y1
		}
	}_SetPositions(){
		local tx, ty, Positions := {}, sx, sy, lx, ly, cancel
		CoordMode, Mouse, Screen
		While(!GetKeyState("ctrl")){
			if(GetKeyState("Alt")){
				Cancel := True
				break
			}
			MouseGetPos, tx, ty
			if(tx!=lx||ty!=ly){
				lx := tx, ly := ty
				ToolTip, Press "ctrl" to set the first position `nX: %tx% Y: %ty% `nPress "Alt" to cancel
				Loop, % This._GetMonitorCount()	{
					GuiControl, % This.Name[A_Index] ":Move", % This.Cross[A_Index].Horz1, % "x0 y" ty-This.MonitorBounds[A_Index].Y1  " w" This.MonitorBounds[A_Index].X2 - This.MonitorBounds[A_Index].X1 " h1"
					GuiControl, % This.Name[A_Index] ":Move", % This.Cross[A_Index].Vert1,  % "x" tx - This.MonitorBounds[A_Index].X1 " y0 w1 h" This.MonitorBounds[A_Index].Y2 - This.MonitorBounds[A_Index].Y1
				}
			}
			Sleep, 30
		}
		Positions.X1 := tx, Positions.Y1 := ty, lx := "", ly := ""
		ToolTip,
		While(GetKeyState("ctrl")){
			if(Cancel||GetKeyState("Alt")){
				Cancel := True
				break
			}
			Sleep, 30
		}
		While(!GetKeyState("ctrl")){
			if(Cancel||GetKeyState("Alt")){
				Cancel := True
				break
			}
			MouseGetPos, tx, ty
			if(tx!=lx||ty!=ly){
				lx := tx, ly := ty
				ToolTip, Press "ctrl" to set the second position `nX: %tx% Y: %ty% `nPress "Alt" to cancel
				(tx<Positions.X1)?(sx:=tx):(sx:=Positions.X1)
				(ty<Positions.Y1)?(sy:=ty):(sy:=Positions.Y1)
				Gui, HBBackgroundGuiHB:Show, % "x" sx " y" sy " w" ABS(tx-Positions.X1) " h" ABS(ty-Positions.Y1) " NA"
				Loop, % This._GetMonitorCount()	{
					GuiControl, % This.Name[A_Index] ":MoveDraw", % This.Cross[A_Index].Horz2, % "x0 y" ty-This.MonitorBounds[A_Index].Y1  " w" This.MonitorBounds[A_Index].X2 - This.MonitorBounds[A_Index].X1 " h1"
					GuiControl, % This.Name[A_Index] ":MoveDraw", % This.Cross[A_Index].Vert2,  % "x" tx - This.MonitorBounds[A_Index].X1 " y0 w1 h" This.MonitorBounds[A_Index].Y2 - This.MonitorBounds[A_Index].Y1
				}
			}
			Sleep, 30
		}
		Positions.X2 := tx, Positions.Y2 := ty, Positions.W := ABS(Positions.X2-Positions.X1), Positions.H := ABS(Positions.Y2-Positions.Y1)
		ToolTip,
		This._DestroyWindows()	
		return (Cancel)?(0):(Positions)
	}_GetMonitorCount(){
		local MonitorCount
		SysGet, MonitorCount, MonitorCount
		return MonitorCount
	}_GetMonitorBounds(Index){
		local Mon, MonLeft, MonTop, MonRight, MonBottom, MonObj := {}
		SysGet, Mon, Monitor , % Index
		MonObj.X1 := MonLeft, MonObj.Y1 := MonTop, MonObj.X2 := MonRight, MonObj.Y2 := MonBottom
		return MonObj
	}_DestroyWindows(){
		Gui, HBBackgroundGuiHB:Destroy
		Loop, % This._GetMonitorCount()
			Gui, % This.Name[A_Index] ":Destroy"
	}
}
roysubs
Posts: 421
Joined: 29 Sep 2018, 16:37

Re: Snipping Tool automation

12 Feb 2021, 08:15

@Smile_ This is really fantastic, but my only concern with it is that it seems to takes a snip each and every time the mouse is dragged across the screen regardless of what I am doing. Is there a way such that this only triggers when I initiate a capture session by pressing Ctrl+PrintScreen for example?
roysubs
Posts: 421
Joined: 29 Sep 2018, 16:37

Re: Snipping Tool automation

12 Feb 2021, 08:19

@HellBent, this class that you have built is incredible! Only problem is that I've got that function working, and the cross-hairs appear then I do Ctrl the first time to start the snip, then Ctrl again to end the snip, but I don't seem to have anything at the end of the operation ... is that by design? You are just giving me the co-ordinates, then I should perform a snip using another function afterwards?
User avatar
Smile_
Posts: 857
Joined: 03 May 2020, 00:51

Re: Snipping Tool automation

12 Feb 2021, 08:40

Use another key combination for example ( Alt + Left Mouse Button )

Code: Select all

CoordMode, Mouse, Screen
~Alt & LButton::
    MouseGetPos, Xi, Yi
Return

~Alt & LButton up::
    MouseGetPos, Xf, Yf
    If (Xi > Xf)
    {
        Aux := Xi
        Xi := Xf
        Xf := Aux
    }
    If (Yi > Yf)
    {
        Aux := Yi
        Yi := Yf
        Yf := Aux
    }
    CaptureScreen(Xi ", " Yi ", " Xf ", " Yf,, A_Desktop "\" A_Now ".png")
Return

^#printscreen::
    WinGetTitle, Title, A
    WinGetPos, X, Y, Width, Height, %Title%
    Width += X, Height += Y
    CaptureScreen(X ", " Y ", " Width ", " Height,, A_Desktop "\" A_Now ".png")
Return
Also fixed an issue with getting image dimensions.
roysubs
Posts: 421
Joined: 29 Sep 2018, 16:37

Re: Snipping Tool automation

12 Feb 2021, 10:32

This version is really great @Smile_, love it(!!!), ALT + mouse drag works amazingly. Only possible thing that might be nice is if it can be combined with @HellBent's class that he's built to show the crosshairs also (so maybe: CTRL+PrintScreen to activate, then just ALT + LeftMouse + drag to mark out the area).
User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: Snipping Tool automation

12 Feb 2021, 10:35

roysubs wrote:
12 Feb 2021, 08:19
@HellBent, this class that you have built is incredible! Only problem is that I've got that function working, and the cross-hairs appear then I do Ctrl the first time to start the snip, then Ctrl again to end the snip, but I don't seem to have anything at the end of the operation ... is that by design? You are just giving me the co-ordinates, then I should perform a snip using another function afterwards?
Yeah you would need to add in the code to take a screenshot of the selected area. Here is a example with some code for taking a screenshot.

Code: Select all

;*****************************************************************
#Include <TargetArea>   ;https://www.autohotkey.com/boards/viewtopic.php?f=6&t=85494
#Include <My Altered Gdip Lib>  ;<------       Replace with your copy of GDIP
;*****************************************************************
#SingleInstance, Force
SetBatchLines, -1
return

^PrintScreen::
	KeyWait, Ctrl
	if( Positions := TargetArea.Set( "Blue" ) ){
		SX := Positions.X1 < Positions.X2  ?  Positions.X1  : Positions.X2
		SY := Positions.Y1 < Positions.Y2  ?  Positions.Y1  : Positions.Y2
		pToken := Gdip_Startup() 
		ClipBitmap := Gdip_BitmapFromScreen( SX "|" SY "|" Positions.W "|" Positions.H ) 
		Gdip_SaveBitmapToFile( ClipBitmap , A_WorkingDir "\" ( ( SaveToFile = 1 ) ? ( ClipName := "Saved Clip " A_Now ) : ( ClipName := "Temp Clip" ) ) ".png" , 100 ) 
		Gdip_DisposeImage( ClipBitmap ) 
		Gdip_Shutdown( pToken ) 
		
	}else{
		msgbox, Operation Canceled
	}
	return

*ESC::ExitApp
roysubs
Posts: 421
Joined: 29 Sep 2018, 16:37

Re: Snipping Tool automation

13 Feb 2021, 05:10

I'm now using these four Hotkey, and they work amazingly well I have to say, apart from ^#printscreen:: which unlike the Windows snipping tool creates a region of about 8 pixels around the left, right, and bottom of the image (but *not* the top, which is defined quite nicely. Update: Fixed it (somewhat). I modified the values for Width and Height, and this does quite nicely trim the right side and bottom, "Width += X-8, Height += Y-8", and found eventually that I can just change the X value by +8 in the CaptureScreen function to get a well defined image). Only downside is that a Visual Studio Code windows (only this application and nothing else I have seen, will lose a few pixels from the bottom, I don't have a fix for that - it is a minor annoyance and mostly nothing to worry about).

The four functions are then:

• PrintScreen: Pressed on it's own will take a full screenshot and save it to a timestamped file on disk. Added a little pop sound happens on capture also. File is "<date-time Full screen.png"
• Ctrl+Win+PrintScreen: Will take a snip of the active Window. Saves the snip to a timestamped file on disk. Added a little pop sound. File is "<date-time Window.png"
• Alt+Left Mouse: hold down Alt and then hold down the left mouse button to set a corner and then drag the mouse to define a region, then let go of the mouse to capture that region. it in the clipboard and also saving it to a timestamped file on disk. Added a little pop sound on pressing Alt+Left click and then another pop on releasing the Left mouse button. File is "<date-time Mouse region.png"
• Ctrl+Win+Alt+PrintScreen: Open the contents of the last defined snip file (variable SnipFile) created by any of the above three actions in the default image file viewer.

Notes:
• All files save under a Screenshots folder on the users Desktop for easy access. The names will always sort in order of capture as have put the "date-time" part at start of filename.
• I have prevented all 3 functions from copying into the clipboard. This could be useful, but would overwrite any text that was since accessing the file is so easy (

All in, this is a complete replacement for every image capture app functionality that I've ever needed and works amazingly well. Thanks for all of the help with this! :)

Code: Select all

*~$printscreen::
    Screenshots := "C:\Users\" A_UserName "\Desktop\Screenshots"
    IfNotExist, %Screenshots%
        FileCreateDir, %Screenshots%
    SnipFile := Screenshots "\" A_YYYY "-" A_MM "-" A_DD " " A_Hour "-" A_Min "-" A_Sec " Full screen.png"
	CaptureScreen(0, 0, SnipFile)
    SoundBeep, 500, 5
return

~Alt & LButton::
    MouseGetPos, Xi, Yi
Return

~Alt & LButton up::
    MouseGetPos, Xf, Yf
    If (Xi > Xf)
    {
        Aux := Xi
        Xi := Xf
        Xf := Aux
    }
    If (Yi > Yf)
    {
        Aux := Yi
        Yi := Yf
        Yf := Aux
    }
    Screenshots := "C:\Users\" A_UserName "\Desktop\Screenshots" 
    IfNotExist, %Screenshots%
        FileCreateDir, %Screenshots%
    SnipFile := Screenshots "\" A_YYYY "-" A_MM "-" A_DD " " A_Hour "-" A_Min "-" A_Sec " Mouse region.png"
    CaptureScreen(Xi ", " Yi ", " Xf ", " Yf,, SnipFile)
    SoundBeep, 500, 5
Return

^#printscreen::
    WinGetTitle, Title, A
    WinGetPos, X, Y, Width, Height, %Title%   ; MsgBox, %Title%`n%X%`n%Y%`n%Width%`n%Height%
    Width += X-8, Height += Y-8
    Screenshots := "C:\Users\" A_UserName "\Desktop\Screenshots" 
    IfNotExist, %Screenshots%
        FileCreateDir, %Screenshots%
    SnipFile := Screenshots "\" A_YYYY "-" A_MM "-" A_DD " " A_Hour "-" A_Min "-" A_Sec " Window.png"
    CaptureScreen(X+8 ", " Y ", " Width ", " Height,, SnipFile)
    SoundBeep, 500, 5
Return

^#!printscreen::
    Run, %SnipFile%
Return

; Note that if the Microsoft PowerToys are installed and one or more images are selected in Windows Explorer,
; then Ctrl+Win+P will open the ImageResizer tool https://www.bricelam.net/ImageResizer/


;-----------------------------------------------------------------------------------------------------------
; https://autohotkey.com/board/topic/121619-screencaptureahk-broken-capturescreen-function-win-81-x64/ LinearSpoon (2015-02-20)
; CaptureScreen(aRect, bCursor, sFileTo, nQuality)
;
; 1) If the optional parameter bCursor is True, captures the cursor too.
; 2) If the optional parameter sFileTo is 0, set the image to Clipboard.
;    If it is omitted or "", saves to screen.bmp in the script folder,
;    otherwise to sFileTo which can be BMP/JPG/PNG/GIF/TIF.
; 3) The optional parameter nQuality is applicable only when sFileTo is JPG. Set it to the desired quality level of the resulting JPG, an integer between 0 - 100.
; 4) If aRect is 0/1/2/3, captures the entire desktop/active window/active client area/active monitor.
; 5) aRect can be comma delimited sequence of coordinates, e.g., "Left, Top, Right, Bottom" or "Left, Top, Right, Bottom, Width_Zoomed, Height_Zoomed".
;    In this case, only that portion of the rectangle will be captured. Additionally, in the latter case, zoomed to the new width/height, Width_Zoomed/Height_Zoomed.
;
; Example:
; CaptureScreen(0)
; CaptureScreen(1)
; CaptureScreen(2)
; CaptureScreen(3)
; CaptureScreen("100, 100, 200, 200")
; CaptureScreen("100, 100, 200, 200, 400, 400")   ; Zoomed
;-----------------------------------------------------------------------------------------------------------
; Convert(sFileFr, sFileTo, nQuality)
; Convert("C:\image.bmp", "C:\image.jpg")
; Convert("C:\image.bmp", "C:\image.jpg", 95)
; Convert(0, "C:\clip.png")   ; Save the bitmap in the clipboard to sFileTo if sFileFr is "" or 0.

CaptureScreen(aRect = 0, bCursor = False, sFile = "", nQuality = "")
{
	If !aRect
	{
		SysGet, nL, 76  ; virtual screen left & top
		SysGet, nT, 77
		SysGet, nW, 78	; virtual screen width and height
		SysGet, nH, 79
	}
	Else If aRect = 1
		WinGetPos, nL, nT, nW, nH, A
	Else If aRect = 2
	{
		WinGet, hWnd, ID, A
		VarSetCapacity(rt, 16, 0)
		DllCall("GetClientRect" , "ptr", hWnd, "ptr", &rt)
		DllCall("ClientToScreen", "ptr", hWnd, "ptr", &rt)
		nL := NumGet(rt, 0, "int")
		nT := NumGet(rt, 4, "int")
		nW := NumGet(rt, 8)
		nH := NumGet(rt,12)
	}
	Else If aRect = 3
	{
		VarSetCapacity(mi, 40, 0)
		DllCall("GetCursorPos", "int64P", pt), NumPut(40,mi,0,"uint")
		DllCall("GetMonitorInfo", "ptr", DllCall("MonitorFromPoint", "int64", pt, "Uint", 2, "ptr"), "ptr", &mi)
		nL := NumGet(mi, 4, "int")
		nT := NumGet(mi, 8, "int")
		nW := NumGet(mi,12, "int") - nL
		nH := NumGet(mi,16, "int") - nT
	}
	Else
	{
		StringSplit, rt, aRect, `,, %A_Space%%A_Tab%
		nL := rt1	; convert the Left,top, right, bottom into left, top, width, height
		nT := rt2
		nW := rt3 - rt1
		nH := rt4 - rt2
		znW := rt5
		znH := rt6
	}

	mDC := DllCall("CreateCompatibleDC", "ptr", 0, "ptr")
	hBM := CreateDIBSection(mDC, nW, nH)
	oBM := DllCall("SelectObject", "ptr", mDC, "ptr", hBM, "ptr")
	hDC := DllCall("GetDC", "ptr", 0, "ptr")
	DllCall("BitBlt", "ptr", mDC, "int", 0, "int", 0, "int", nW, "int", nH, "ptr", hDC, "int", nL, "int", nT, "Uint", 0x40CC0020)
	DllCall("ReleaseDC", "ptr", 0, "ptr", hDC)
	If bCursor
		CaptureCursor(mDC, nL, nT)
	DllCall("SelectObject", "ptr", mDC, "ptr", oBM)
	DllCall("DeleteDC", "ptr", mDC)
	If znW && znH
		hBM := Zoomer(hBM, nW, nH, znW, znH)
	If sFile = 0
		SetClipboardData(hBM)
	Else Convert(hBM, sFile, nQuality), DllCall("DeleteObject", "ptr", hBM)
}

CaptureCursor(hDC, nL, nT)
{
	VarSetCapacity(mi, 32, 0), Numput(16+A_PtrSize, mi, 0, "uint")
	DllCall("GetCursorInfo", "ptr", &mi)
	bShow   := NumGet(mi, 4, "uint")
	hCursor := NumGet(mi, 8)
	xCursor := NumGet(mi,8+A_PtrSize, "int")
	yCursor := NumGet(mi,12+A_PtrSize, "int")

	DllCall("GetIconInfo", "ptr", hCursor, "ptr", &mi)
	xHotspot := NumGet(mi, 4, "uint")
	yHotspot := NumGet(mi, 8, "uint")
	hBMMask  := NumGet(mi,8+A_PtrSize)
	hBMColor := NumGet(mi,16+A_PtrSize)

	If bShow
		DllCall("DrawIcon", "ptr", hDC, "int", xCursor - xHotspot - nL, "int", yCursor - yHotspot - nT, "ptr", hCursor)
	If hBMMask
		DllCall("DeleteObject", "ptr", hBMMask)
	If hBMColor
		DllCall("DeleteObject", "ptr", hBMColor)
}

Zoomer(hBM, nW, nH, znW, znH)
{
	mDC1 := DllCall("CreateCompatibleDC", "ptr", 0, "ptr")
	mDC2 := DllCall("CreateCompatibleDC", "ptr", 0, "ptr")
	zhBM := CreateDIBSection(mDC2, znW, znH)
	oBM1 := DllCall("SelectObject", "ptr", mDC1, "ptr",  hBM, "ptr")
	oBM2 := DllCall("SelectObject", "ptr", mDC2, "ptr", zhBM, "ptr")
	DllCall("SetStretchBltMode", "ptr", mDC2, "int", 4)
	DllCall("StretchBlt", "ptr", mDC2, "int", 0, "int", 0, "int", znW, "int", znH, "ptr", mDC1, "int", 0, "int", 0, "int", nW, "int", nH, "Uint", 0x00CC0020)
	DllCall("SelectObject", "ptr", mDC1, "ptr", oBM1)
	DllCall("SelectObject", "ptr", mDC2, "ptr", oBM2)
	DllCall("DeleteDC", "ptr", mDC1)
	DllCall("DeleteDC", "ptr", mDC2)
	DllCall("DeleteObject", "ptr", hBM)
	Return zhBM
}

Convert(sFileFr = "", sFileTo = "", nQuality = "")
{
	If (sFileTo = "")
		sFileTo := A_ScriptDir . "\screen.bmp"
	SplitPath, sFileTo, , sDirTo, sExtTo, sNameTo
	
	If Not hGdiPlus := DllCall("LoadLibrary", "str", "gdiplus.dll", "ptr")
		Return	sFileFr+0 ? SaveHBITMAPToFile(sFileFr, sDirTo (sDirTo = "" ? "" : "\") sNameTo ".bmp") : ""
	VarSetCapacity(si, 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", "UintP", pToken, "ptr", &si, "ptr", 0)

	If !sFileFr
	{
		DllCall("OpenClipboard", "ptr", 0)
		If	(DllCall("IsClipboardFormatAvailable", "Uint", 2) && (hBM:=DllCall("GetClipboardData", "Uint", 2, "ptr")))
			DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "ptr", hBM, "ptr", 0, "ptr*", pImage)
		DllCall("CloseClipboard")
	}
	Else If	sFileFr Is Integer
		DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "ptr", sFileFr, "ptr", 0, "ptr*", pImage)
	Else	DllCall("gdiplus\GdipLoadImageFromFile", "wstr", sFileFr, "ptr*", pImage)
	DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
	VarSetCapacity(ci,nSize,0)
	DllCall("gdiplus\GdipGetImageEncoders", "Uint", nCount, "Uint", nSize, "ptr", &ci)
	struct_size := 48+7*A_PtrSize, offset := 32 + 3*A_PtrSize, pCodec := &ci - struct_size
	Loop, %	nCount
		If InStr(StrGet(Numget(offset + (pCodec+=struct_size)), "utf-16") , "." . sExtTo)
			break

	If (InStr(".JPG.JPEG.JPE.JFIF", "." . sExtTo) && nQuality<>"" && pImage && pCodec < &ci + nSize)
	{
		DllCall("gdiplus\GdipGetEncoderParameterListSize", "ptr", pImage, "ptr", pCodec, "UintP", nCount)
		VarSetCapacity(pi,nCount,0), struct_size := 24 + A_PtrSize
		DllCall("gdiplus\GdipGetEncoderParameterList", "ptr", pImage, "ptr", pCodec, "Uint", nCount, "ptr", &pi)
		Loop, %	NumGet(pi,0,"uint")
			If (NumGet(pi,struct_size*(A_Index-1)+16+A_PtrSize,"uint")=1 && NumGet(pi,struct_size*(A_Index-1)+20+A_PtrSize,"uint")=6)
			{
				pParam := &pi+struct_size*(A_Index-1)
				NumPut(nQuality,NumGet(NumPut(4,NumPut(1,pParam+0,"uint")+16+A_PtrSize,"uint")),"uint")
				Break
			}
	}

	If pImage
		pCodec < &ci + nSize	? DllCall("gdiplus\GdipSaveImageToFile", "ptr", pImage, "wstr", sFileTo, "ptr", pCodec, "ptr", pParam) : DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "ptr", pImage, "ptr*", hBitmap, "Uint", 0) . SetClipboardData(hBitmap), DllCall("gdiplus\GdipDisposeImage", "ptr", pImage)

	DllCall("gdiplus\GdiplusShutdown" , "Uint", pToken)
	DllCall("FreeLibrary", "ptr", hGdiPlus)
}


CreateDIBSection(hDC, nW, nH, bpp = 32, ByRef pBits = "")
{
	VarSetCapacity(bi, 40, 0)
	NumPut(40, bi, "uint")
	NumPut(nW, bi, 4, "int")
	NumPut(nH, bi, 8, "int")
	NumPut(bpp, NumPut(1, bi, 12, "UShort"), 0, "Ushort")
	Return DllCall("gdi32\CreateDIBSection", "ptr", hDC, "ptr", &bi, "Uint", 0, "UintP", pBits, "ptr", 0, "Uint", 0, "ptr")
}

SaveHBITMAPToFile(hBitmap, sFile)
{
	VarSetCapacity(oi,104,0)
	DllCall("GetObject", "ptr", hBitmap, "int", 64+5*A_PtrSize, "ptr", &oi)
	fObj := FileOpen(sFile, "w")
	fObj.WriteShort(0x4D42)
	fObj.WriteInt(54+NumGet(oi,36+2*A_PtrSize,"uint"))
	fObj.WriteInt64(54<<32)
	fObj.RawWrite(&oi + 16 + 2*A_PtrSize, 40)
	fObj.RawWrite(NumGet(oi, 16+A_PtrSize), NumGet(oi,36+2*A_PtrSize,"uint"))
	fObj.Close()
}

SetClipboardData(hBitmap)
{
	VarSetCapacity(oi,104,0)
	DllCall("GetObject", "ptr", hBitmap, "int", 64+5*A_PtrSize, "ptr", &oi)
	sz := NumGet(oi,36+2*A_PtrSize,"uint")
	hDIB :=	DllCall("GlobalAlloc", "Uint", 2, "Uptr", 40+sz, "ptr")
	pDIB := DllCall("GlobalLock", "ptr", hDIB, "ptr")
	DllCall("RtlMoveMemory", "ptr", pDIB, "ptr", &oi + 16 + 2*A_PtrSize, "Uptr", 40)
	DllCall("RtlMoveMemory", "ptr", pDIB+40, "ptr", NumGet(oi, 16+A_PtrSize), "Uptr", sz)
	DllCall("GlobalUnlock", "ptr", hDIB)
	DllCall("DeleteObject", "ptr", hBitmap)
	DllCall("OpenClipboard", "ptr", 0)
	DllCall("EmptyClipboard")
	DllCall("SetClipboardData", "Uint", 8, "ptr", hDIB)
	DllCall("CloseClipboard")
}
User avatar
HiSoKa
Posts: 480
Joined: 27 Jan 2020, 15:43

Re: Snipping Tool automation

16 Sep 2021, 12:49

Hellbent wrote:
12 Feb 2021, 10:35
roysubs wrote:
12 Feb 2021, 08:19
@HellBent, this class that you have built is incredible! Only problem is that I've got that function working, and the cross-hairs appear then I do Ctrl the first time to start the snip, then Ctrl again to end the snip, but I don't seem to have anything at the end of the operation ... is that by design? You are just giving me the co-ordinates, then I should perform a snip using another function afterwards?
Yeah you would need to add in the code to take a screenshot of the selected area. Here is a example with some code for taking a screenshot.

Code: Select all

;*****************************************************************
#Include <TargetArea>   ;https://www.autohotkey.com/boards/viewtopic.php?f=6&t=85494
#Include <My Altered Gdip Lib>  ;<------       Replace with your copy of GDIP
;*****************************************************************
#SingleInstance, Force
SetBatchLines, -1
return

^PrintScreen::
	KeyWait, Ctrl
	if( Positions := TargetArea.Set( "Blue" ) ){
		SX := Positions.X1 < Positions.X2  ?  Positions.X1  : Positions.X2
		SY := Positions.Y1 < Positions.Y2  ?  Positions.Y1  : Positions.Y2
		pToken := Gdip_Startup() 
		ClipBitmap := Gdip_BitmapFromScreen( SX "|" SY "|" Positions.W "|" Positions.H ) 
		Gdip_SaveBitmapToFile( ClipBitmap , A_WorkingDir "\" ( ( SaveToFile = 1 ) ? ( ClipName := "Saved Clip " A_Now ) : ( ClipName := "Temp Clip" ) ) ".png" , 100 ) 
		Gdip_DisposeImage( ClipBitmap ) 
		Gdip_Shutdown( pToken ) 
		
	}else{
		msgbox, Operation Canceled
	}
	return

*ESC::ExitApp
Hello @Hellbent Thank you for your great code
But I facing a problem.
I downloaded [Class] TargetArea and Gdip.ahk
and written your code

Code: Select all

;*****************************************************************
#Include TargetArea.ahk   ;https://www.autohotkey.com/boards/viewtopic.php?f=6&t=85494
#Include Gdip_All.ahk  ;<------       Replace with your copy of GDIP
;*****************************************************************
#SingleInstance, Force
SetBatchLines, -1
return

^PrintScreen::
KeyWait, Ctrl
if( Positions := TargetArea.Set( "Blue" ) ){
	SX := Positions.X1 < Positions.X2  ?  Positions.X1  : Positions.X2
	SY := Positions.Y1 < Positions.Y2  ?  Positions.Y1  : Positions.Y2
	pToken := Gdip_Startup() 
	ClipBitmap := Gdip_BitmapFromScreen( SX "|" SY "|" Positions.W "|" Positions.H ) 
	Gdip_SaveBitmapToFile( ClipBitmap , A_WorkingDir "\" ( ( SaveToFile = 1 ) ? ( ClipName := "Saved Clip " A_Now ) : ( ClipName := "Temp Clip" ) ) ".png" , 100 ) 
	Gdip_DisposeImage( ClipBitmap ) 
	Gdip_Shutdown( pToken ) 
	
}else{
	msgbox, Operation Canceled
}
return

*ESC::ExitApp
that problem is that after I click on a Ctrl to set secound Position nothing happens, and it does not save screenshot..
User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: Snipping Tool automation

16 Sep 2021, 17:54

HiSoKa wrote:
16 Sep 2021, 12:49
that problem is that after I click on a Ctrl to set secound Position nothing happens, and it does not save screenshot..
Hi. I tried running your code (changed the path for the #Includes and the hotkey) and it seems to work fine.
I take a shot and then in the folder there is a png named "Temp Clip".

The way it is in your script is that unless you set the Variable "SaveToFile" to a value of 1 it overwrites the same image each time you take a shot.

Please confirm whether it isn't saving at all (No png called "Temp Clip" in the scripts dir).
User avatar
HiSoKa
Posts: 480
Joined: 27 Jan 2020, 15:43

Re: Snipping Tool automation

16 Sep 2021, 18:33

The code does not create a "Temp Clip" folder for some reason.
I click on ^PrtScr and then I click on Ctrl to set position 1, then drag the mouse pointer and then click on Ctrl again but the code does not save the images,
I don't know why..

Note: I am using windows 7.

Thank you for caring
User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: Snipping Tool automation

16 Sep 2021, 18:57

The script you have doesn't save the image to a folder called "Temp Clip", it creates a png in the scripts A_workingdir with that name.

Assuming that there is in fact an issue beyond you looking in the wrong place. Here is how you can start to debug it.

First, Add a message after the "IF()" and display the results (X1 , X2 , etc) You can find a prewritten msgbox in the example posted in the classes thread
(you posted the link already)

Next add a message and see that the variable "ClipBitmap" has a value. To do it, just add a message after the line "ClipBitmap := GDIP_..."

If a bitmap is created you should get a sting of 8-10 numbers ( something like this "1759236592" )

That should be enough to confirm that things are working as expected.

Other than that.

Add this to the top of the script

Code: Select all

SetWorkingDir, % A_ScriptDir
If you want to put the images in their own folder, add the name to the end of the line above.

i.e

Code: Select all

SetWorkingDir, % A_ScriptDir "\Some Folder\"
With that, images will get saved to a folder (I can't remember if the folder needs to first exist or not use without first doing something like FileCreateDir ) You will find out quick if that is the case.


The last thing (optional)
Remember that unless you want every new image to overwrite the last one you made, you need to set a variable called "SaveToFile" to a value of 1

Code: Select all

SaveToFile := 1
Gdip_SaveBitmapToFile( ClipBitmap , A_WorkingDir "\" ( ( SaveToFile = 1 ) ? ( ClipName := "Saved Clip " A_Now ) : ( ClipName := "Temp Clip" ) ) ".png" , 100 ) 
	

Try going over that and let me know your results.
User avatar
HiSoKa
Posts: 480
Joined: 27 Jan 2020, 15:43

Re: Snipping Tool automation

17 Sep 2021, 10:48

When i added MsgBox after the "IF()" it show me the truth results (this link for video screenshot to more explain https://youtu.be/2Lu-MMJRggw)
When i added a MsgBox to see that variable "ClipBitmap" it show me number "0".
And i added SetWorkingDir, % A_ScriptDir But the problem of not creating the folder images and images still exists
This is the code After modification to find errors to debug them as you mentioned to me:

Code: Select all

;*****************************************************************
#Include TargetArea.ahk   ;https://www.autohotkey.com/boards/viewtopic.php?f=6&t=85494
#Include Gdip_All.ahk  ;<------       Replace with your copy of GDIP
;*****************************************************************
#SingleInstance, Force
SetWorkingDir, % A_ScriptDir
SetBatchLines, -1
return

PrintScreen::
KeyWait, Ctrl
if( Positions := TargetArea.Set( "Blue" ) )
{
	msgbox,% "X1: " Positions.X1 "`nY1: " Positions.Y1 "`nX2: " Positions.X2 "`nY2: " Positions.Y2 "`nW: " Positions.W "`nH: " Positions.H		
	SX := Positions.X1 < Positions.X2  ?  Positions.X1  : Positions.X2
	SY := Positions.Y1 < Positions.Y2  ?  Positions.Y1  : Positions.Y2
	pToken := Gdip_Startup() 
	ClipBitmap := Gdip_BitmapFromScreen( SX "|" SY "|" Positions.W "|" Positions.H ) 
	msgbox, %ClipBitmap%
	Gdip_SaveBitmapToFile( ClipBitmap , A_WorkingDir "\" ( ( SaveToFile = 1 ) ? ( ClipName := "Saved Clip " A_Now ) : ( ClipName := "Temp Clip" ) ) ".png" , 100 ) 
	Gdip_DisposeImage( ClipBitmap ) 
	Gdip_Shutdown( pToken ) 
	
}else{
	msgbox, Operation Canceled
}
return

*ESC::ExitApp
I have a code that you posted a while ago that works for me normally, this is the code:

Code: Select all

;Written By: Hellbent aka CivReborn
;Date: June 15th 2019
;https://www.autohotkey.com/boards/viewtopic.php?f=76&t=69361
#SingleInstance,Force
SetBatchLines,-1
IfNotExist,%A_ScriptDir%\Recorded Shots
	FileCreateDir, %A_ScriptDir%\Temp Screen Shots
SetWorkingDir,%A_ScriptDir%\Temp Screen Shots
Coordmode,Mouse,screen
CoordMode,Pixel,Screen
global CapActive:=0,SP,XCAP,YCAP,WCAP,HCAP,OB:=0,CAPIT:=0
global CapWin:={},Monitors := New MonitorClass()
Gdip_Startup()
global TXC,TYC,BB:=New_Brush("000000","88"),GB:=New_Brush("00ff00","55"),RB:=New_Brush("ff0000","55")


Gui,1:+AlwaysOnTop -DPIScale +HWNDGUI1HWND
Gui,1:Color,333333,444444
Gui,1:Font,cwhite s10 Bold ,Segoe UI
Gui,1:Add,Button,xm ym w300 h30 -Theme gSet_Capture_Area vSCAP,Take Screen Shot
Gui,1:Add,Button,xm w300 h30 -Theme gSet_Capture_Area vSSA,Set Search Area
Gui,1:Add,Button,xm w300 h30 -Theme gImageSearch,Search
Gui,1:Add,Picture,xm y+10 w300 h300 vPic gUpdatePic,% A_WorkingDir "\Test Screen Shot.png"
UpdatePic()
Gui,1:Show,AutoSize,HB Snap it
return
GuiClose:
GuiContextMenu:
2GuiContextMenu:
*ESC::
ExitApp

UpdatePic(){
	static FakePic
	Gui,Fake:Add,Picture,vFakePic,% A_WorkingDir "\Test Screen Shot.png"
	GuiControlGet,Pos,Fake:Pos,FakePic
	Gui,Fake:Destroy
	if(PosW<=300&&PosH<=300){
		NW:=PosW,NH:=PosH
	}else if(PosW>PosH){
		ratio:=PosH/PosW,NW:=300,NH:=300*Ratio
	}else if(PosW<PosH){
		ratio:=PosW/PosH,NH:=300,NW:=300*Ratio
	}else	{
		NW:=300,NH:=300
	}
	GuiControl,1:Move,Pic,% "w" NW " h" NH
	GuiControl,1:,Pic,% A_WorkingDir "\Test Screen Shot.png"
	Gui,1:Show,AutoSize
}

Set_Capture_Area:
	if(A_GuiControl="SCAP")
		CAPIT:=1
	Create_Capture_Size_Window()
	return
	
Numpad3::	
ImageSearch:
	ImageSearch,foundx,foundy,XCAP,YCAP,XCAP+WCAP,YCAP+HCAP,%A_WorkingDir%\Test Screen Shot.png
	if(ErrorLevel=0){
		SoundBeep,500
		MouseMove,FoundX+20,FoundY+20
	}else if(ErrorLevel=1){
		Loop 3
			SoundBeep,600
	}
	return

Create_Capture_Size_Window(){
	static ft
	Gui,2:Destroy
	CapWin:=Layered_Window_SetUp(3,0,0,A_ScreenWidth,A_ScreenHeight,"2","+AlwaysOnTop -DPIScale -Caption +Owner1")
	Max:=Monitors.Get_Largest_Monitor_Size()
	CapWin.hbm:=CreateDIBSection(Max.Width,Max.Height)
	CapWin.hdc := CreateCompatibleDC()
	CapWin.obm := SelectObject(CapWin.hdc,CapWin.hbm),CapWin.G := Gdip_GraphicsFromHDC(CapWin.hdc)
	Gdip_SetSmoothingMode(CapWin.G,3)

	;~ ToolTip,% Max.Width "`n" Max.Height
	if(!ft){
		Monitors.Set_Window_Move_Timer(GUINAME:=2,GUIHWND:=CapWin.hwnd,TCount:=300,xpOff:=0,ypOff:=0,xr:=1,yr:=1,Fill_Screen:=1)
		ft:=1
	}else 	{
		Monitors.Window_Move_Obj.GUIHWND:=CapWin.hwnd
		Monitors.Turn_On_Window_Move_Timer()
	}
	CapActive:=1,SP:=0,OB:=0
	SetTimer,Set_Positions,10
}

Set_Positions(){
	Coordmode,Mouse,Window
	If(!WinActive("ahk_Id" CapWin.Hwnd)){
		WinActivate,% "ahk_Id" CapWin.Hwnd
	}
	Gdip_GraphicsClear(CapWin.g)
	MouseGetPos,tx,ty
	if(SP=0){
		Fill_Box(CapWin.G,BB,tx,0,1,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Bottom-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top)
		Fill_Box(CapWin.G,BB,0,ty,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Right-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,1)
		TXC:=tx,TYC:=ty
	}else if(SP=1){
		;~ Monitors.Turn_Off_Window_Move_Timer()
		Fill_Box(CapWin.G,BB,TXC,0,1,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Bottom-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top)
		Fill_Box(CapWin.G,BB,0,TYC,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Right-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,1)
		Fill_Box(CapWin.G,BB,tx,0,1,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Bottom-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top)
		Fill_Box(CapWin.G,BB,0,ty,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Right-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,1)
		if(TXC<tx&&TYC<ty){
			Fill_Box(CapWin.G,GB,TXC,TYC,tx-TXC,ty-TYC)
			WCAP:=tx-TXC,HCAP:=ty-TYC,OB:=0
			XCAP:=TXC+Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,YCAP:=TYC+Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top
		}else if(TXC>tx&&TYC<ty){
			Fill_Box(CapWin.G,RB,tx,TYC,TXC-tx,ty-TYC)
			OB:=1
		}else if(TXC>tx&&TYC>ty){
			Fill_Box(CapWin.G,RB,tx,ty,TXC-tx,TYC-ty)
			OB:=1
		}else if(TXC<tx&&TYC>ty){
			Fill_Box(CapWin.G,RB,TXC,ty,tx-TXC,TYC-ty)
			OB:=1
		}
	}
	UpdateLayeredWindow(CapWin.hwnd, CapWin.hdc,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top,Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Right-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Left, Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Bottom-Monitors.Monitor[Monitors.Window_Move_Obj.Current_Monitor].Top)
}

#IF (CapActive=1)
	LButton::
		if(SP=0)
			SP:=1
		else if(SP=1&&OB=0){
			Monitors.Turn_Off_Window_Move_Timer()
			CapActive:=0
			SelectObject(CapWin.hdc,CapWin.obm),DeleteObject(CapWin.hbm),DeleteDC(CapWin.hdc),gdip_deleteGraphics(CapWin.g)
			CapWin:="",SP:=0
			Gui,2:Destroy
			SetTimer,Set_Positions,Off
			if(CAPIT)
				gosub,Take_ScreenShot
		}
		return
#IF

Numpad1::
	SelectObject(CapWin.hdc,CapWin.obm),DeleteObject(CapWin.hbm),DeleteDC(CapWin.hdc),gdip_deleteGraphics(CapWin.g)
	CapWin:="",SP:=0,CapActive:=0,CAPIT:=1
	Create_Capture_Size_Window()
	return
	
Numpad2::
	SelectObject(CapWin.hdc,CapWin.obm),DeleteObject(CapWin.hbm),DeleteDC(CapWin.hdc),gdip_deleteGraphics(CapWin.g)
	CapWin:="",SP:=0,CapActive:=0,CAPIT:=0
	Create_Capture_Size_Window()
	return

Take_ScreenShot:
	CAPIT:=0
	TempBitmap:=Gdip_BitmapFromScreen(XCAP "|" YCAP "|" WCAP "|" HCAP)
	Gdip_SaveBitmapToFile(TempBitmap,A_WorkingDir "\Test Screen Shot.png", 100)
	Gdip_DisposeImage(TempBitmap)
	SoundBeep,400,300
	UpdatePic()
	return	

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

class MonitorClass	{
	__New(){
		This._SetMonCount()
		This._SetPrimeMonitor()
		This._Set_Bounds()
	}
	_SetMonCount(){
		local MC
		SysGet, MC, MonitorCount 
		This.MonitorCount := MC
	}
	_SetPrimeMonitor(){
		local PM
		SysGet, PM, MonitorPrimary
		This.PrimeMonitor := PM
	}
	_Set_Bounds(){
		local bmon,bmonLeft,bmonRight,bmonTop,bmonBottom
		This.Monitors:=[]
		Loop,% This.MonitorCount	{
			SysGet, bmon, Monitor, % A_Index
			This.Monitor[A_Index]:=	{ Left		: 	bmonLeft
									, Top		: 	bmonTop
									, Right		: 	bmonRight
									, Bottom	: 	bmonBottom 	}
		}
	}
	Get_Current_Monitor(){
		local x,y
		CoordMode,Mouse,Screen
		MouseGetPos,x,y
		Loop,% This.MonitorCount	{
			if(x>=This.Monitor[A_Index].Left&&x<=This.Monitor[A_Index].Right&&y>=This.Monitor[A_Index].Top&&y<=This.Monitor[A_Index].Bottom){
				return A_Index
			}
		}
	}
	Get_New_Window_Position(curMon,xpOff,ypOff,xr,yr){
		local tposa:="",tposa:={}
		if(xr=1) ; 1 xr = relative to the left side ; 2 xr = relative to the right side
			tposa.x:=This.Monitor[curMon].Left+xpOff
		else 
			tposa.x:=This.Monitor[curMon].Right-xpOff
		if(yr=1) ; 1 yr = relative to the top  ; 2 yr = relative to the bottom
			tposa.y:=This.Monitor[curMon].Top+ypOff
		else 
			tposa.y:=This.Monitor[curMon].Bottom-ypOff
		return tposa
	}
	Set_Window_Move_Timer(GUINAME:=1,GUIHWND:="",TCount:=500,xpOff:=0,ypOff:=0,xr:=1,yr:=1,Fill_Screen:=0){
		
		local Window_Timer
		
		This.Window_Move_Obj:=	{ 	Interval		:	TCount
								,	GUINAME			:	GUINAME
								,	FILLSCREEN		:	Fill_Screen
								,	GUIHWND			:	GUIHWND
								,	XPOFF			:	xpOff
								,	YPOFF			:	ypOff
								,	XRelative		:	xr
								,	YRelative		:	yr	
								,	Current_Monitor	:	This.Get_Current_Monitor()
								,	Old_Monitor		:	This.Get_Current_Monitor()	
								,	NEW_GUI_POS		:	This.Get_New_Window_Position(This.Get_Current_Monitor(),xpOff,ypOff,xr,yr)	}
								
		This.Window_Timer := Window_Timer :=  ObjBindMethod(This, "_Window_Move_Timer")
		
		This._Set_TFTime()
		
		SetTimer,%Window_Timer%,%TCount%

	}
	Get_Largest_Monitor_Size(){
		local tempMSW:="",tempMSH:=""
		Loop,% This.MonitorCount	{
			if(This.Monitor[A_Index].Right-This.Monitor[A_Index].Left>=This.Monitor[A_Index+1].Right-This.Monitor[A_Index+1].Left&&This.Monitor[A_Index].Right-This.Monitor[A_Index].Left>=This.Monitor[tempMSW].Right-This.Monitor[tempMSW].Left)
				tempMSW:=A_index
			if(This.Monitor[A_Index].Bottom-This.Monitor[A_Index].Top>=This.Monitor[A_Index+1].Bottom-This.Monitor[A_Index+1].Top&&This.Monitor[A_Index].Bottom-This.Monitor[A_Index].Top>=This.Monitor[tempMSH].Bottom-This.Monitor[tempMSH].Top)
				tempMSH:=A_index
		}
		This.Max_Monitor_Dimensions := {Width: This.Monitor[tempMSW].Right-This.Monitor[tempMSW].Left, Height: This.Monitor[tempMSH].Bottom-This.Monitor[tempMSH].Top}
		return This.Max_Monitor_Dimensions
	}
	_Window_Move_Timer(){
		This.Window_Move_Obj.Current_Monitor := This.Get_Current_Monitor()
		if(This.Window_Move_Obj.Current_Monitor!=This.Window_Move_Obj.Old_Monitor&&!DllCall("IsIconic", "Ptr", This.Window_Move_Obj.GUIHWND, "UInt")){
			This.Window_Move_Obj.NEW_GUI_POS:=This.Get_New_Window_Position(This.Window_Move_Obj.Current_Monitor,This.Window_Move_Obj.XPOFF,This.Window_Move_Obj.YPOFF,This.Window_Move_Obj.XRelative,This.Window_Move_Obj.YRelative)
			This._Move_Window()
			This.Window_Move_Obj.Old_Monitor := This.Window_Move_Obj.Current_Monitor
		}
	}
	_Set_TFTime(){
		This.Window_Move_Obj.Current_Monitor := This.Get_Current_Monitor()
		This.Window_Move_Obj.NEW_GUI_POS:=This.Get_New_Window_Position(This.Window_Move_Obj.Current_Monitor,This.Window_Move_Obj.XPOFF,This.Window_Move_Obj.YPOFF,This.Window_Move_Obj.XRelative,This.Window_Move_Obj.YRelative)
		This.Window_Move_Obj.Old_Monitor := This.Window_Move_Obj.Current_Monitor
		This._Move_Window()
	}
	_Move_Window(){
		if(!This.Window_Move_Obj.FILLSCREEN)
			Gui,% This.Window_Move_Obj.GUINAME ":Show",% "x" This.Window_Move_Obj.NEW_GUI_POS.X " y" This.Window_Move_Obj.NEW_GUI_POS.Y " NA"
		else
			Gui,% This.Window_Move_Obj.GUINAME ":Show",% "x" This.Window_Move_Obj.NEW_GUI_POS.X " y" This.Window_Move_Obj.NEW_GUI_POS.Y " w" This.Monitor[This.Window_Move_Obj.Current_Monitor].Right " h" This.Monitor[This.Window_Move_Obj.Current_Monitor].Bottom " NA"
	}
	Turn_Off_Window_Move_Timer(){
		local Window_Timer
		Window_Timer := This.Window_Timer
		SetTimer,%Window_Timer%,Off
	}
	Turn_On_Window_Move_Timer(){
		local Window_Timer
		Window_Timer := This.Window_Timer
		This._Set_TFTime()
		SetTimer,%Window_Timer%,On
	}
	GetGuiPos(){
		local x,y
		WinGetPos,x,y,,,% "ahk_id " This.Window_Move_Obj.GUIHWND 
		return x
	}
}
;######################################################################################################################################
;#####################################################   					    #######################################################
;#####################################################  	  Gdip LITE		    #######################################################
;#####################################################  					    #######################################################
;######################################################################################################################################
Layered_Window_SetUp(Smoothing,Window_X,Window_Y,Window_W,Window_H,Window_Name:=1,Window_Options:=""){
	Layered:={}
	Layered.W:=Window_W,Layered.H:=Window_H,Layered.X:=Window_X,Layered.Y:=Window_Y
	Layered.Name:=Window_Name,Layered.Options:=Window_Options
	;~ Layered.Token:=Gdip_Startup()
	Create_Layered_GUI(Layered),Layered.hwnd:=winExist()
	;~ Layered.hbm := CreateDIBSection(Window_W,Window_H),Layered.hdc := CreateCompatibleDC()
	;~ Layered.obm := SelectObject(Layered.hdc,Layered.hbm),Layered.G := Gdip_GraphicsFromHDC(Layered.hdc)
	;~ Gdip_SetSmoothingMode(Layered.G,Smoothing)
	return Layered
}
Create_Layered_GUI(Layered){
	Gui,% Layered.Name ": +E0x80000 +LastFound " Layered.Options 
	Gui,% Layered.Name ":Show",% "x" Layered.X " y" Layered.Y " w" Layered.W " h" Layered.H ;" NA"
}	
Layered_Window_ShutDown(This){
	SelectObject(This.hdc,This.obm),DeleteObject(This.hbm),DeleteDC(This.hdc)
	gdip_deleteGraphics(This.g),Gdip_Shutdown(This.Token)
}
New_Brush(colour:="000000",Alpha:="FF"){
	new_colour := "0x" Alpha colour 
	return Gdip_BrushCreateSolid(new_colour)
}
New_Pen(colour:="000000",Alpha:="FF",Width:= 5){
	new_colour := "0x" Alpha colour 
	return Gdip_CreatePen(New_Colour,Width)
}	
Fill_Box(pGraphics,pBrush,x,y,w,h)	{
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdiplus\GdipFillRectangle", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
}
; Gdip standard library v1.45 by tic (Tariq Porter) 07/09/11
; Modifed by Rseding91 using fincs 64 bit compatible Gdip library 5/1/2013
BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster=""){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdi32\BitBlt", Ptr, dDC, "int", dx, "int", dy, "int", dw, "int", dh, Ptr, sDC, "int", sx, "int", sy, "uint", Raster ? Raster : 0x00CC0020)
}
Gdip_SetImageAttributesColorMatrix(Matrix){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	VarSetCapacity(ColourMatrix, 100, 0)
	Matrix := RegExReplace(RegExReplace(Matrix, "^[^\d-\.]+([\d\.])", "$1", "", 1), "[^\d-\.]+", "|")
	StringSplit, Matrix, Matrix, |
	Loop, 25
	{
		Matrix := (Matrix%A_Index% != "") ? Matrix%A_Index% : Mod(A_Index-1, 6) ? 0 : 1
		NumPut(Matrix, ColourMatrix, (A_Index-1)*4, "float")
	}
	DllCall("gdiplus\GdipCreateImageAttributes", A_PtrSize ? "UPtr*" : "uint*", ImageAttr)
	DllCall("gdiplus\GdipSetImageAttributesColorMatrix", Ptr, ImageAttr, "int", 1, "int", 1, Ptr, &ColourMatrix, Ptr, 0, "int", 0)
	return ImageAttr
}
Gdip_GetImageWidth(pBitmap){
   DllCall("gdiplus\GdipGetImageWidth", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Width)
   return Width
}
Gdip_GetImageHeight(pBitmap){
   DllCall("gdiplus\GdipGetImageHeight", A_PtrSize ? "UPtr" : "UInt", pBitmap, "uint*", Height)
   return Height
}
Gdip_DeletePen(pPen){
   return DllCall("gdiplus\GdipDeletePen", A_PtrSize ? "UPtr" : "UInt", pPen)
}
Gdip_DeleteBrush(pBrush){
   return DllCall("gdiplus\GdipDeleteBrush", A_PtrSize ? "UPtr" : "UInt", pBrush)
}
Gdip_DisposeImage(pBitmap){
   return DllCall("gdiplus\GdipDisposeImage", A_PtrSize ? "UPtr" : "UInt", pBitmap)
}
Gdip_DeleteGraphics(pGraphics){
   return DllCall("gdiplus\GdipDeleteGraphics", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}
Gdip_DisposeImageAttributes(ImageAttr){
	return DllCall("gdiplus\GdipDisposeImageAttributes", A_PtrSize ? "UPtr" : "UInt", ImageAttr)
}
CreateCompatibleDC(hdc=0){
   return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
SelectObject(hdc, hgdiobj){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}
DeleteObject(hObject){
   return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
}
GetDC(hwnd=0){
	return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}
GetDCEx(hwnd, flags=0, hrgnClip=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
    return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
}
ReleaseDC(hdc, hwnd=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}
DeleteDC(hdc){
   return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
Gdip_SetClipRegion(pGraphics, Region, CombineMode=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdiplus\GdipSetClipRegion", Ptr, pGraphics, Ptr, Region, "int", CombineMode)
}
CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	NumPut(w, bi, 4, "uint"), NumPut(h, bi, 8, "uint"), NumPut(40, bi, 0, "uint"), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16, "uInt"), NumPut(bpp, bi, 14, "ushort")
	hbm := DllCall("CreateDIBSection", Ptr, hdc2, Ptr, &bi, "uint", 0, A_PtrSize ? "UPtr*" : "uint*", ppvBits, Ptr, 0, "uint", 0, Ptr)
	if !hdc
		ReleaseDC(hdc2)
	return hbm
}
Gdip_GraphicsFromHDC(hdc){
    DllCall("gdiplus\GdipCreateFromHDC", A_PtrSize ? "UPtr" : "UInt", hdc, A_PtrSize ? "UPtr*" : "UInt*", pGraphics)
    return pGraphics
}
Gdip_GetDC(pGraphics){
	DllCall("gdiplus\GdipGetDC", A_PtrSize ? "UPtr" : "UInt", pGraphics, A_PtrSize ? "UPtr*" : "UInt*", hdc)
	return hdc
}
Gdip_Startup(){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	if !DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("LoadLibrary", "str", "gdiplus")
	VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0), si := Chr(1)
	DllCall("gdiplus\GdiplusStartup", A_PtrSize ? "UPtr*" : "uint*", pToken, Ptr, &si, Ptr, 0)
	return pToken
}
Gdip_CreatePen(ARGB, w){
   DllCall("gdiplus\GdipCreatePen1", "UInt", ARGB, "float", w, "int", 2, A_PtrSize ? "UPtr*" : "UInt*", pPen)
   return pPen
}
Gdip_BrushCreateSolid(ARGB=0xff000000){
	DllCall("gdiplus\GdipCreateSolidFill", "UInt", ARGB, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
}
Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0){
	DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "UInt", ARGBfront, "UInt", ARGBback, A_PtrSize ? "UPtr*" : "UInt*", pBrush)
	return pBrush
}
CreateRectF(ByRef RectF, x, y, w, h){
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}
CreatePointF(ByRef PointF, x, y){
   VarSetCapacity(PointF, 8)
   NumPut(x, PointF, 0, "float"), NumPut(y, PointF, 4, "float")
}
Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("gdiplus\GdipFillRectangle", Ptr, pGraphics, Ptr, pBrush, "float", x, "float", y, "float", w, "float", h)
}
Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0){
   return DllCall("gdiplus\GdipSetClipRect",  A_PtrSize ? "UPtr" : "UInt", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
}
Gdip_ResetClip(pGraphics){
   return DllCall("gdiplus\GdipResetClip", A_PtrSize ? "UPtr" : "UInt", pGraphics)
}
Gdip_SetSmoothingMode(pGraphics, SmoothingMode){
   return DllCall("gdiplus\GdipSetSmoothingMode", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", SmoothingMode)
}
Gdip_GraphicsClear(pGraphics, ARGB=0x00ffffff){
    return DllCall("gdiplus\GdipGraphicsClear", A_PtrSize ? "UPtr" : "UInt", pGraphics, "int", ARGB)
}
UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	if ((x != "") && (y != ""))
		VarSetCapacity(pt, 8), NumPut(x, pt, 0, "UInt"), NumPut(y, pt, 4, "UInt")
	if (w = "") ||(h = "")
		WinGetPos,,, w, h, ahk_id %hwnd%
	return DllCall("UpdateLayeredWindow", Ptr, hwnd, Ptr, 0, Ptr, ((x = "") && (y = "")) ? 0 : &pt, "int64*", w|h<<32, Ptr, hdc, "int64*", 0, "uint", 0, "UInt*", Alpha<<16|1<<24, "uint", 2)
}
Gdip_BitmapFromScreen(Screen=0, Raster=""){
	if (Screen = 0){
		Sysget, x, 76
		Sysget, y, 77	
		Sysget, w, 78
		Sysget, h, 79
	}
	else if (SubStr(Screen, 1, 5) = "hwnd:")
	{
		Screen := SubStr(Screen, 6)
		if !WinExist( "ahk_id " Screen)
			return -2
		WinGetPos,,, w, h, ahk_id %Screen%
		x := y := 0
		hhdc := GetDCEx(Screen, 3)
	}
	else if (Screen&1 != "")
	{
		Sysget, M, Monitor, %Screen%
		x := MLeft, y := MTop, w := MRight-MLeft, h := MBottom-MTop
	}
	else
	{
		StringSplit, S, Screen, |
		x := S1, y := S2, w := S3, h := S4
	}
	if (x = "") || (y = "") || (w = "") || (h = "")
		return -1
	chdc := CreateCompatibleDC(), hbm := CreateDIBSection(w, h, chdc), obm := SelectObject(chdc, hbm), hhdc := hhdc ? hhdc : GetDC()
	BitBlt(chdc, 0, 0, w, h, hhdc, x, y, Raster)
	ReleaseDC(hhdc)
	pBitmap := Gdip_CreateBitmapFromHBITMAP(hbm)
	SelectObject(chdc, obm), DeleteObject(hbm), DeleteDC(hhdc), DeleteDC(chdc)
	return pBitmap
}
Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	SplitPath, sOutput,,, Extension
	if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
		return -1
	Extension := "." Extension
	DllCall("gdiplus\GdipGetImageEncodersSize", "uint*", nCount, "uint*", nSize)
	VarSetCapacity(ci, nSize)
	DllCall("gdiplus\GdipGetImageEncoders", "uint", nCount, "uint", nSize, Ptr, &ci)
	if !(nCount && nSize)
		return -2
	If (A_IsUnicode){
		StrGet_Name := "StrGet"
		Loop, %nCount%
		{
			sString := %StrGet_Name%(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+idx
			break
		}
	} else {
		Loop, %nCount%
		{
			Location := NumGet(ci, 76*(A_Index-1)+44)
			nSize := DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "uint", 0, "int",  0, "uint", 0, "uint", 0)
			VarSetCapacity(sString, nSize)
			DllCall("WideCharToMultiByte", "uint", 0, "uint", 0, "uint", Location, "int", -1, "str", sString, "int", nSize, "uint", 0, "uint", 0)
			if !InStr(sString, "*" Extension)
				continue
			
			pCodec := &ci+76*(A_Index-1)
			break
		}
	}
	if !pCodec
		return -3
	if (Quality != 75)
	{
		Quality := (Quality < 0) ? 0 : (Quality > 100) ? 100 : Quality
		if Extension in .JPG,.JPEG,.JPE,.JFIF
		{
			DllCall("gdiplus\GdipGetEncoderParameterListSize", Ptr, pBitmap, Ptr, pCodec, "uint*", nSize)
			VarSetCapacity(EncoderParameters, nSize, 0)
			DllCall("gdiplus\GdipGetEncoderParameterList", Ptr, pBitmap, Ptr, pCodec, "uint", nSize, Ptr, &EncoderParameters)
			Loop, % NumGet(EncoderParameters, "UInt")      ;%
			{
				elem := (24+(A_PtrSize ? A_PtrSize : 4))*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
				if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
				{
					p := elem+&EncoderParameters-pad-4
					NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
					break
				}
			}      
		}
	}
	if (!A_IsUnicode)
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, 0, "int", 0)
		VarSetCapacity(wOutput, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, Ptr, &sOutput, "int", -1, Ptr, &wOutput, "int", nSize)
		VarSetCapacity(wOutput, -1)
		if !VarSetCapacity(wOutput)
			return -4
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &wOutput, Ptr, pCodec, "uint", p ? p : 0)
	}
	else
		E := DllCall("gdiplus\GdipSaveImageToFile", Ptr, pBitmap, Ptr, &sOutput, Ptr, pCodec, "uint", p ? p : 0)
	return E ? -5 : 0
}
Gdip_Shutdown(pToken){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	DllCall("gdiplus\GdiplusShutdown", Ptr, pToken)
	if hModule := DllCall("GetModuleHandle", "str", "gdiplus", Ptr)
		DllCall("FreeLibrary", Ptr, hModule)
	return 0
}
Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
	return pBitmap
}
It works fine but I'm wondering why the first code doesn't work for me.
User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: Snipping Tool automation

17 Sep 2021, 11:41

Thanks for the video :thumbup:

I ran the code and it works fine for me.
Try this next.

Comment out the gdip #Includes and copy / paste in the GDIP LITE section from the bottom of the other script and run again.
User avatar
HiSoKa
Posts: 480
Joined: 27 Jan 2020, 15:43

Re: Snipping Tool automation

17 Sep 2021, 11:58

Wow :dance: , Now it works as expected after deleting #Include Gdip_All.ahk and adding the GDIP LITE section..
Thanks a million @Hellbent :salute: ..
User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: Snipping Tool automation

17 Sep 2021, 12:02

HiSoKa wrote:
17 Sep 2021, 11:58
Wow :dance: , Now it works as expected after deleting #Include Gdip_All.ahk and adding the GDIP LITE section..
Thanks a million @Hellbent :salute: ..
NP :thumbup:

It means that you have a issue with your gdip lib.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: marypoppins_1, mikeyww, Rohwedder, RussF and 131 guests