Snipping Tool automation
Snipping Tool automation
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
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
Re: Snipping Tool automation
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.
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 ===================================
Re: Snipping Tool automation
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"
}
}
Re: Snipping Tool automation
@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?
Re: Snipping Tool automation
@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?
Re: Snipping Tool automation
Use another key combination for example ( Alt + Left Mouse Button )
Also fixed an issue with getting image dimensions.
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
Re: Snipping Tool automation
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).
Re: Snipping Tool automation
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.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?
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
Re: Snipping Tool automation
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!
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")
}
Re: Snipping Tool automation
here also example from user 'teadrinker' and irfanview
;- https://www.autohotkey.com/boards/viewtopic.php?f=76&t=66245
;- https://www.autohotkey.com/boards/viewtopic.php?p=284814#p284814 ;- teadrinker
;- https://www.autohotkey.com/boards/viewtopic.php?p=378441#p378441 ; irfanview
;- https://www.autohotkey.com/boards/viewtopic.php?f=76&t=66245
;- https://www.autohotkey.com/boards/viewtopic.php?p=284814#p284814 ;- teadrinker
;- https://www.autohotkey.com/boards/viewtopic.php?p=378441#p378441 ; irfanview
Re: Snipping Tool automation
Hello @Hellbent Thank you for your great codeHellbent wrote: ↑12 Feb 2021, 10:35Yeah 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.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?
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
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
Re: Snipping Tool automation
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).
Re: Snipping Tool automation
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
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
Re: Snipping Tool automation
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
If you want to put the images in their own folder, add the name to the end of the line above.
i.e
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
Try going over that and let me know your results.
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
i.e
Code: Select all
SetWorkingDir, % A_ScriptDir "\Some Folder\"
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.
Re: Snipping Tool automation
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:
I have a code that you posted a while ago that works for me normally, this is the code:
It works fine but I'm wondering why the first code doesn't work for me.
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
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
}
Re: Snipping Tool automation
Thanks for the video
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.
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.
Re: Snipping Tool automation
Wow , Now it works as expected after deleting #Include Gdip_All.ahk and adding the GDIP LITE section..
Thanks a million @Hellbent ..
Thanks a million @Hellbent ..