Create Screenshot specific area Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
feeko
Posts: 51
Joined: 15 Apr 2022, 00:20

Re: Create Screenshot specific area

Post by feeko » 24 May 2022, 10:14

Thanks for the quick response @boiler.

I tried adding "% clipboard" in these spots. The results was "% clipboard - Test".

Code: Select all

snap := Gdip_BitmapFromScreen("1400|148|1142|1163")
Gdip_SaveBitmapToFile(snap, "C:\Users\Owner\Desktop\% clipboard - Test.png")

fPath := "C:\Users\Owner\Desktop"
Gdip_SaveBitmapToFile(snap,fPath "\% clipboard - Test.png")

Gdip_SaveBitmapToFile(snap,A_Desktop "\% clipboard - Test.png")
So it's not possible to add the contents of the clipboard to the saved file name?

I have to manually rename the file each time and was curious if I could just copy the name (text) before taking the screenshot and have it automatically add it to the file name.

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 24 May 2022, 10:20

Sorry, I misunderstood. I thought you were trying to add the text to the contents of the image itself.

You can do what you are asking. You just need to use the correct syntax as shown below. You have a basic misunderstanding of how to write expressions, especially concatenation of variables and literal strings.

Code: Select all

snap := Gdip_BitmapFromScreen("1400|148|1142|1163")
Gdip_SaveBitmapToFile(snap, "C:\Users\Owner\Desktop\" clipboard " - Test.png")

fPath := "C:\Users\Owner\Desktop"
Gdip_SaveBitmapToFile(snap,fPath "\" clipboard " - Test.png")

Gdip_SaveBitmapToFile(snap,A_Desktop "\" clipboard " - Test.png")

You should make sure your clipboard doesn't contain any characters that are not allowed in file names.

feeko
Posts: 51
Joined: 15 Apr 2022, 00:20

Re: Create Screenshot specific area

Post by feeko » 24 May 2022, 10:45

@boiler is "clipboard" and "% clipboard" the difference between the old version of AHK and the newer one?

edit: Thank you that worked

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 24 May 2022, 10:53

No, they are part of the same latest version of AHK. You are just misapplying the concept of forcing an expression using a % followed by a space. You don't use it within an expression, let alone within a quoted string in an expression. It is used to tell AHK that you are writing an expression in a command parameter that is otherwise expecting legacy syntax. Where you tried to use it was where an expression was already expected (a function parameter), and you wouldn't put it inside a quoted string in any case.

User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Create Screenshot specific area

Post by FanaticGuru » 24 May 2022, 17:03

boiler wrote:
24 May 2022, 09:45
You would have to modify the image to add text to it.

Here is a function that adds text to an image

Code: Select all

; [Function] Image_TextBox
; Fanatic Guru
; 2018 11 11
;
; Function to use Gdip to add text to image
;
;{-----------------------------------------------
;
; Image_TextBox(Text, FilePath, SavePath, Options*)
;
; Parameters:
;	Text			text to add to image
;	FilePath	path to source file, blank to use image on Clipboard
;	SavePath	path to save modified image, blank to save modified image to Clipboard
;	Options*	variadic parameter for pseudo named paramater options
;		For each named parameter use the format "Name=value"
;		FontSize		text font size (default "FontSize=24")
;		Font				text font name (default "Font=Arial")
;		Style				text font style; Regular|Bold|Italic|BoldItalic|Underline|Strikeout (default "Style=Regular")
;		Align			alignment of text; Near|Left|Centre|Center|Far|Right and Top|Up|Bottom|Down|vCentre|vCenter (default "Align=Center vCenter")
;		Margin			clear space between border and text boundary (default "Margin=0")
;		TextColor		color of text with alpha transparant, hex aarrggbb (default "TextColor=ffffffff" solid white)
;		BoxColor		color of box fill with alpha transparent, hex aarrggbb (default "BoxColor=ff000000" solid black)
;		BorderColor	color of border with alpha transparent, hex aarrggbb (default "BorderColor=ffff0000" solid red)
;		Weight			weight or thickness of border, 0 weight is no border (default "Weight=2")
;		Render			rendering hint; (default "Render=0")
;							0: SystemDefault, 1: SingleBitPerPixelGridFit, 2: SingleBitPerPixel, 3: AntiAliasGridFit, 4: AntiAlias, 5: ClearTypeGridFit
;		Pos				position of box; Left|Right|Top|Botton|vCenter or XY in format "x,y" or percentage in format ".x,.y"; 
;								negative amounts goes from right or bottom (default "Pos=Bottom Left")
;								examples "Pos=vCenter" vertical center or "Pos=100,200" 100 x 200 y or 
;									"Pos=.1,.2" 10% x 20% y or "Pos=-20,-.10" 20 x from right, 10% y from bottom
;		Quality			quality for images with compression format (default "Quality=75")
;		BoxSize		size of box in format "x,y" or "" to autofit (default "BoxSize=Auto")
;
; 	Notes: text will word wrap within box and `n can be used for new line
;
;	Example:
;	Image_TextBox("Example Text","Image_Test.PNG",, "FontSize=48", "Weight=6", "Margin=10", "Style=Bold",  "Align=Right vCenter", "BoxSize=200,100", "Pos=-20,-.20", "BoxColor=55000000", "Render=5")
;
Image_TextBox(Text:="", FilePath:="", SavePath:="", Options*)
{
	; Default Options
	FontSize:=24, Font:="Arial",  Style:="Regular", Align:="Center vCenter", Margin:=0, TextColor:="ffffffff", BoxColor:="ff000000", BorderColor:="ffff0000", Weight:="2", Render:=0, Pos:="Bottom Left", Quality:=75, BoxSize:="Auto"
	; Options as Named Parameters
	for key, Option in Options
	{
		Opt := StrSplit(Option, "=")
		var := Opt.1, val := Opt.2
		%var% := val
	}
	; Startup Gdip
	if !pToken
	{
		If !pToken := Gdip_Startup()
		{
		   MsgBox, 48, Gdip+ Error!, Gdip+ failed to start. Please ensure you have Gdip+ on your system.
		   ExitApp
		}
		else
		{
			OnExit, Exit_Image_TextBox
			If !Gdip_FontFamilyCreate(Font)
			{
			   MsgBox, 48, Font Error!, The font you have specified does not exist on the system.
			   ExitApp
			}
		}
	}
	; Get Bitmap, Graphics, Pen, and Brush
	if FilePath
		pBitmapFile := Gdip_CreateBitmapFromFile(FilePath)
	else
		pBitmapFile := Gdip_CreateBitmapFromClipboard()
	pG := Gdip_GraphicsFromImage(pBitmapFile)
	Gdip_SetSmoothingMode(pG, 4)
	pPen := Gdip_CreatePen("0x" BorderColor, Weight)
	pBrush := Gdip_BrushCreateSolid("0x" BoxColor)
	; Get Width and Height of components
	Width := Gdip_GetImageWidth(pBitmapFile)
	Height := Gdip_GetImageHeight(pBitmapFile)
	if (!BoxSize or BoxSize="Auto")
	{
		Options :=  "c" TextColor " s" FontSize " r" Render " " Style " " Align
		Measure := StrSplit(Gdip_TextToGraphics(pG, Text, Options, Font,,,true), "|")
		Box_Width := Measure.3 + (Weight * 2) + (Margin * 2)
		Box_Height := Measure.4 + (Weight * 2) + (Margin * 2)
	}
	else
	{
		XY := StrSplit(BoxSize, ",")
		Box_Width := XY.1, Box_Height := XY.2
	}
	; Process Number Box Position Options
	if InStr(Pos, ",")
	{
		XY := StrSplit(Pos, ",")
		if (0 < XY.1 and XY.1 < 1)
			Box_X := Width * XY.1
		else if (-1 < XY.1 and XY.1 < 0)
			Box_X := Width + (Width * XY.1) - Box_Width - 1
		else if (XY.1 < 0)
			Box_X := Width + XY.1 - Box_Width  - 1 
		else
			Box_X := XY.1
		if (0 < XY.2 and XY.2 < 1)
			Box_Y := Height * XY.2
		else if (-1 < XY.2 and XY.2 < 0)
			Box_Y := Height + (Height * XY.2) - Box_Height - 1
		else if (XY.2 < 0)
			Box_Y := Height + XY.2 - Box_Height - 1
		else
			Box_Y := XY.2
		Pos := XY.3
	}
	; Process Word Box Position Options
	if InStr(Pos, "Left")
		Box_X := 0
	else if InStr(Pos, "Right")
		Box_X := Width - Box_Width - 1
	else if (Pos ~= "(?<!v)Center")
		Box_X := (Width - Box_Width) / 2 - 1
	if InStr(Pos, "Bottom")
		Box_Y := Height - Box_Height - 1
	else if InStr(Pos, "Top")
		Box_Y := 0
	else if InStr(Pos, "vCenter")
		Box_Y := (Height - Box_Height) / 2 - 1
	Border_X := Box_X + Weight / 2, Border_Y := Box_Y + Weight / 2
	Border_Width := Box_Width - Weight, Border_Height := Box_Height - Weight
	; Text X, Y, Width, Height
	Padding := Margin + Weight
	Text_X := Box_X + Padding - 1, Text_Y := Box_Y + Padding - 1
	Text_Width := Box_Width - (Padding * 2), Text_Height := Box_Height - (Padding * 2)
	; Draw Box, Border, and Text
	Gdip_FillRectangle(pG, pBrush, Box_X, Box_Y, Box_Width, Box_Height)
	if Weight
		Gdip_DrawRectangle(pG, pPen, Border_X, Border_Y, Border_Width, Border_Height)
	Options := "c" TextColor " s" FontSize " r" Render " " Style " " Align " x" Text_X " y" Text_Y 
	Gdip_TextToGraphics(pG, Text, Options, Font, Text_Width, Text_Height)
	; Process Result
	if  SavePath
		Gdip_SaveBitmapToFile(pBitmapFile, SavePath, Quality)
	else
		Gdip_SetBitmapToClipboard(pBitmapFile)
	; Destroy Pen, Brush, Bitmap, and Graphic
	Gdip_DeletePen(pPen)
	Gdip_DeleteBrush(pBrush)
	Gdip_DisposeImage(pBitmapFile)
	Gdip_DeleteGraphics(pG)
	return
	; On Exit, make sure all Pointers Destroyed and Gdip Shutdown
	Exit_Image_TextBox:
		Gdip_DeletePen(pPen)
		Gdip_DeleteBrush(pBrush)
		Gdip_DisposeImage(pBitmapFile)
		Gdip_DeleteGraphics(pG)
		Gdip_Shutdown(pToken)
		ExitApp
	return
}
; }

Here is some examples:

Code: Select all

#Include [Function] Image_TextBox.ahk

F1::
	send !{PrintScreen} ; get an image of current window on the clipboard for testing
	Sleep 500
	Comment = Default Bottom Left`nSize to Fit`nCenter Text
	Image_TextBox(Comment)
	DisplayClipboardInGui()
return

F2::
	send !{PrintScreen} ; get an image of current window on the clipboard for testing
	Sleep 500
	Comment = Bigger Font with Style`nPostion 30 from Left`n150 from Bottom
	Image_TextBox(Comment,,, "FontSize=36", "Weight=6", "Margin=10", "Style=Bold",  "Pos=30,-150")
	DisplayClipboardInGui()
return

F3::
	send !{PrintScreen} ; get an image of current window on the clipboard for testing
	Sleep 500
	Comment = Bigger Font with Style`nText Aligned Right with Vertical Center Text Wrap`nSpecific Box Size`nPostion 15`% from Right`n10`% from Top`nColor Fill with Transparent
	Image_TextBox(Comment,,, "FontSize=36", "Weight=6", "Margin=10", "Style=Bold",  "Align=Right vCenter", "BoxSize=515,400", "Pos=-.15,.10", "BoxColor=55ff0000", "Render=5")
	DisplayClipboardInGui()
return

; display modified image on clipboard in GUI
DisplayClipboardInGui()
{
	static
	Gui, Destroy
	if DllCall("OpenClipboard", "uint", 0) {
		if DllCall("IsClipboardFormatAvailable", "uint", 8) {
			hBitmap := DllCall("GetClipboardData", "uint", 2)
		}
		DllCall("CloseClipboard")
	}
	Gui, Add, Pic, vPic, % "HBITMAP:*" hBitmap
	Gui, Show
}

Esc::ExitApp

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 24 May 2022, 17:14

FanaticGuru wrote: Here is a function that adds text to an image
Thanks for sharing that. :thumbup:

It turns out I was wrong in thinking that's what OP wanted, but that's a very useful function in general.

LAPIII
Posts: 668
Joined: 01 Aug 2021, 06:01

Re: Create Screenshot specific area

Post by LAPIII » 24 May 2022, 21:58

This script:

Code: Select all

; doesn't work with YouTube live streams and some videos
#SingleInstance, Force
#Include C:\Users\LPIII\Documents\AutoHotkey\Lib\GDIP_All.ahk
#Include C:\Users\LPIII\Documents\AutoHotkey\Lib\Gdip_ImageSearch.ahk
SetWorkingDir, C:\Users\LPIII\Pictures\Captures   


^+PrintScreen::
FormatTime, DateTime,, d-M-yy h⦂mm⦂ss tt
WinGetActiveTitle, Title
Screenshot(Title "_" DateTime ".png")
Screenshot(OutFile)

{
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen("30|140|1309|655")
Gdip_SaveBitmapToFile(pBitmap, OutFile)
Gdip_DisposeImage(snap)		;Dispose of the bitmap to free memory.
Gdip_Shutdown( pToken ) 	;Turn off gdip
return
}

ToolTipFont("s14", "Comic Sans MS") 
ToolTipColor("green", "white")
ToolTip, Fixed Region Screenshot, 1525, 0
SetTimer, RemoveToolTip, -1000 ; Remove ToolTip after 1 second.
return

RemoveToolTip:
ToolTip
return

; ToolTipOpt v1.004
 
ToolTipFont(Options := "", Name := "", hwnd := "") {
    static hfont := 0
    if (hwnd = "")
        hfont := Options="Default" ? 0 : _TTG("Font", Options, Name), _TTHook()
    else
        DllCall("SendMessage", "ptr", hwnd, "uint", 0x30, "ptr", hfont, "ptr", 0)
}
 
ToolTipColor(Background := "", Text := "", hwnd := "") {
    static bc := "", tc := ""
    if (hwnd = "") {
        if (Background != "")
            bc := Background="Default" ? "" : _TTG("Color", Background)
        if (Text != "")
            tc := Text="Default" ? "" : _TTG("Color", Text)
        _TTHook()
    }
    else {
        VarSetCapacity(empty, 2, 0)
        DllCall("UxTheme.dll\SetWindowTheme", "ptr", hwnd, "ptr", 0
            , "ptr", (bc != "" && tc != "") ? &empty : 0)
        if (bc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1043, "ptr", bc, "ptr", 0)
        if (tc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1044, "ptr", tc, "ptr", 0)
    }
}
 
_TTHook() {
    static hook := 0
    if !hook
        hook := DllCall("SetWindowsHookExW", "int", 4
            , "ptr", RegisterCallback("_TTWndProc"), "ptr", 0
            , "uint", DllCall("GetCurrentThreadId"), "ptr")
}
 
_TTWndProc(nCode, _wp, _lp) {
    Critical 999
   ;lParam  := NumGet(_lp+0*A_PtrSize)
   ;wParam  := NumGet(_lp+1*A_PtrSize)
    uMsg    := NumGet(_lp+2*A_PtrSize, "uint")
    hwnd    := NumGet(_lp+3*A_PtrSize)
    if (nCode >= 0 && (uMsg = 1081 || uMsg = 1036)) {
        _hack_ = ahk_id %hwnd%
        WinGetClass wclass, %_hack_%
        if (wclass = "tooltips_class32") {
            ToolTipColor(,, hwnd)
            ToolTipFont(,, hwnd)
        }
    }
    return DllCall("CallNextHookEx", "ptr", 0, "int", nCode, "ptr", _wp, "ptr", _lp, "ptr")
}
 
_TTG(Cmd, Arg1, Arg2 := "") {
    static htext := 0, hgui := 0
    if !htext {
        Gui _TTG: Add, Text, +hwndhtext
        Gui _TTG: +hwndhgui +0x40000000
    }
    Gui _TTG: %Cmd%, %Arg1%, %Arg2%
    if (Cmd = "Font") {
        GuiControl _TTG: Font, %htext%
        SendMessage 0x31, 0, 0,, ahk_id %htext%
        return ErrorLevel
    }
    if (Cmd = "Color") {
        hdc := DllCall("GetDC", "ptr", htext, "ptr")
        SendMessage 0x138, hdc, htext,, ahk_id %hgui%
        clr := DllCall("GetBkColor", "ptr", hdc, "uint")
        DllCall("ReleaseDC", "ptr", htext, "ptr", hdc)
        return clr
    }
}

won't work on some videos such as:



It also won't work on live streams. I tried different browsers and ShareX screenshot tool works. Have you got any idea why is this problem or of a solution?

LAPIII
Posts: 668
Joined: 01 Aug 2021, 06:01

Re: Create Screenshot specific area

Post by LAPIII » 08 Jun 2022, 10:21

@Boiler Why won't description capture things like AHK script error dialogues:

Code: Select all

; doesn't work with YouTube live streams and some videos
#SingleInstance, Force
#Include C:\Users\LPIII\Documents\AutoHotkey\Lib\GDIP_All.ahk
#Include C:\Users\LPIII\Documents\AutoHotkey\Lib\Gdip_ImageSearch.ahk
SetWorkingDir, C:\Users\LPIII\Pictures\Captures   


^+PrintScreen::
FormatTime, DateTime,, d-M-yy h⦂mm⦂ss tt
WinGetActiveTitle, Title
Screenshot(Title "_" DateTime ".png")
Screenshot(OutFile)

{
pToken := Gdip_Startup()
pBitmap := Gdip_BitmapFromScreen("30|140|1309|655")
Gdip_SaveBitmapToFile(pBitmap, OutFile)
Gdip_DisposeImage(snap)		;Dispose of the bitmap to free memory.
Gdip_Shutdown( pToken ) 	;Turn off gdip
return
}

ToolTipFont("s14", "Comic Sans MS") 
ToolTipColor("green", "white")
ToolTip, Fixed Region Screenshot, 1525, 0
SetTimer, RemoveToolTip, -1000 ; Remove ToolTip after 1 second.
return

RemoveToolTip:
ToolTip
return

; ToolTipOpt v1.004
 
ToolTipFont(Options := "", Name := "", hwnd := "") {
    static hfont := 0
    if (hwnd = "")
        hfont := Options="Default" ? 0 : _TTG("Font", Options, Name), _TTHook()
    else
        DllCall("SendMessage", "ptr", hwnd, "uint", 0x30, "ptr", hfont, "ptr", 0)
}
 
ToolTipColor(Background := "", Text := "", hwnd := "") {
    static bc := "", tc := ""
    if (hwnd = "") {
        if (Background != "")
            bc := Background="Default" ? "" : _TTG("Color", Background)
        if (Text != "")
            tc := Text="Default" ? "" : _TTG("Color", Text)
        _TTHook()
    }
    else {
        VarSetCapacity(empty, 2, 0)
        DllCall("UxTheme.dll\SetWindowTheme", "ptr", hwnd, "ptr", 0
            , "ptr", (bc != "" && tc != "") ? &empty : 0)
        if (bc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1043, "ptr", bc, "ptr", 0)
        if (tc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1044, "ptr", tc, "ptr", 0)
    }
}
 
_TTHook() {
    static hook := 0
    if !hook
        hook := DllCall("SetWindowsHookExW", "int", 4
            , "ptr", RegisterCallback("_TTWndProc"), "ptr", 0
            , "uint", DllCall("GetCurrentThreadId"), "ptr")
}
 
_TTWndProc(nCode, _wp, _lp) {
    Critical 999
   ;lParam  := NumGet(_lp+0*A_PtrSize)
   ;wParam  := NumGet(_lp+1*A_PtrSize)
    uMsg    := NumGet(_lp+2*A_PtrSize, "uint")
    hwnd    := NumGet(_lp+3*A_PtrSize)
    if (nCode >= 0 && (uMsg = 1081 || uMsg = 1036)) {
        _hack_ = ahk_id %hwnd%
        WinGetClass wclass, %_hack_%
        if (wclass = "tooltips_class32") {
            ToolTipColor(,, hwnd)
            ToolTipFont(,, hwnd)
        }
    }
    return DllCall("CallNextHookEx", "ptr", 0, "int", nCode, "ptr", _wp, "ptr", _lp, "ptr")
}
 
_TTG(Cmd, Arg1, Arg2 := "") {
    static htext := 0, hgui := 0
    if !htext {
        Gui _TTG: Add, Text, +hwndhtext
        Gui _TTG: +hwndhgui +0x40000000
    }
    Gui _TTG: %Cmd%, %Arg1%, %Arg2%
    if (Cmd = "Font") {
        GuiControl _TTG: Font, %htext%
        SendMessage 0x31, 0, 0,, ahk_id %htext%
        return ErrorLevel
    }
    if (Cmd = "Color") {
        hdc := DllCall("GetDC", "ptr", htext, "ptr")
        SendMessage 0x138, hdc, htext,, ahk_id %hgui%
        clr := DllCall("GetBkColor", "ptr", hdc, "uint")
        DllCall("ReleaseDC", "ptr", htext, "ptr", hdc)
        return clr
    }
}

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 08 Jun 2022, 16:48

Not sure what you're asking. What happens when you try? Is it producing an image at all? Is it not producing an image of the part of the screen you expected but someplace else? How did you choose your coordinates?

LAPIII
Posts: 668
Joined: 01 Aug 2021, 06:01

Re: Create Screenshot specific area

Post by LAPIII » 08 Jun 2022, 18:22

I'm so sorry bro, I posted completely the wrong script. Here is my Active Screenshot script that with AHK error dialogues it will capture an image of another part of the screen:

Code: Select all

; doesn't work with unmaximized File Explorer Windows
#NoTrayIcon
#SingleInstance, Force
#Include C:\Users\LPIII\Documents\AutoHotkey\Lib\GDIP_All.ahk
SetWorkingDir, C:\Users\LPIII\Pictures\Captures   

ToolTipFont("s14", "Comic Sans MS") 
ToolTipColor("green", "white")
return

!PrintScreen::
ToolTip, Active Window Screenshot, 1525, 0
SetTimer, RemoveToolTip, -500
WinGetPos, X, Y, W, H, A
Area := "(" X "|" Y "|" W "|" H ")"
FormatTime, DateTime,, d-M-yy h-mm-ss tt
WinGetActiveTitle, Title
Screenshot(Title "_" DateTime ".png")
return

Screenshot(OutFile)
{
global Area
pToken := Gdip_Startup()
snap := Gdip_BitmapFromScreen(Area)
Gdip_SaveBitmapToFile(snap, OutFile)
Gdip_DisposeImage(snap)		;Dispose of the bitmap to free memory.
Gdip_Shutdown( pToken ) 	;Turn off gdip
return
}

RemoveToolTip:
ToolTip
return

; ToolTipOpt v1.004
 
ToolTipFont(Options := "", Name := "", hwnd := "") {
    static hfont := 0
    if (hwnd = "")
        hfont := Options="Default" ? 0 : _TTG("Font", Options, Name), _TTHook()
    else
        DllCall("SendMessage", "ptr", hwnd, "uint", 0x30, "ptr", hfont, "ptr", 0)
}
 
ToolTipColor(Background := "", Text := "", hwnd := "") {
    static bc := "", tc := ""
    if (hwnd = "") {
        if (Background != "")
            bc := Background="Default" ? "" : _TTG("Color", Background)
        if (Text != "")
            tc := Text="Default" ? "" : _TTG("Color", Text)
        _TTHook()
    }
    else {
        VarSetCapacity(empty, 2, 0)
        DllCall("UxTheme.dll\SetWindowTheme", "ptr", hwnd, "ptr", 0
            , "ptr", (bc != "" && tc != "") ? &empty : 0)
        if (bc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1043, "ptr", bc, "ptr", 0)
        if (tc != "")
            DllCall("SendMessage", "ptr", hwnd, "uint", 1044, "ptr", tc, "ptr", 0)
    }
}
 
_TTHook() {
    static hook := 0
    if !hook
        hook := DllCall("SetWindowsHookExW", "int", 4
            , "ptr", RegisterCallback("_TTWndProc"), "ptr", 0
            , "uint", DllCall("GetCurrentThreadId"), "ptr")
}
 
_TTWndProc(nCode, _wp, _lp) {
    Critical 999
   ;lParam  := NumGet(_lp+0*A_PtrSize)
   ;wParam  := NumGet(_lp+1*A_PtrSize)
    uMsg    := NumGet(_lp+2*A_PtrSize, "uint")
    hwnd    := NumGet(_lp+3*A_PtrSize)
    if (nCode >= 0 && (uMsg = 1081 || uMsg = 1036)) {
        _hack_ = ahk_id %hwnd%
        WinGetClass wclass, %_hack_%
        if (wclass = "tooltips_class32") {
            ToolTipColor(,, hwnd)
            ToolTipFont(,, hwnd)
        }
    }
    return DllCall("CallNextHookEx", "ptr", 0, "int", nCode, "ptr", _wp, "ptr", _lp, "ptr")
}
 
_TTG(Cmd, Arg1, Arg2 := "") {
    static htext := 0, hgui := 0
    if !htext {
        Gui _TTG: Add, Text, +hwndhtext
        Gui _TTG: +hwndhgui +0x40000000
    }
    Gui _TTG: %Cmd%, %Arg1%, %Arg2%
    if (Cmd = "Font") {
        GuiControl _TTG: Font, %htext%
        SendMessage 0x31, 0, 0,, ahk_id %htext%
        return ErrorLevel
    }
    if (Cmd = "Color") {
        hdc := DllCall("GetDC", "ptr", htext, "ptr")
        SendMessage 0x138, hdc, htext,, ahk_id %hgui%
        clr := DllCall("GetBkColor", "ptr", hdc, "uint")
        DllCall("ReleaseDC", "ptr", htext, "ptr", hdc)
        return clr
    }
}

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 08 Jun 2022, 18:55

Are you sure the dialog is the active window when you press your hotkey?

LAPIII
Posts: 668
Joined: 01 Aug 2021, 06:01

Re: Create Screenshot specific area

Post by LAPIII » 08 Jun 2022, 20:33

Yes, from this:

Image

If I take an active screenshot I get:

Image

which is the size of the window, but missed placed on the screen

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 08 Jun 2022, 22:59

I see why. When I corrected your syntax in your earlier code when you were assigning this:

Code: Select all

Clipboard := "(X" | "Y"| "W" | "H)"
to this:

Code: Select all

Clipboard := "(" X "|" Y "|" W "|" H ")"
…although it corrects your syntax mistakes, I didn’t notice you were passing an incorrect string. You don’t include parentheses in your string. It’s just numbers separated by pipes. So this line in your latest code:

Code: Select all

Area := "(" X "|" Y "|" W "|" H ")"
needs to be this:

Code: Select all

Area := X "|" Y "|" W "|" H

LAPIII
Posts: 668
Joined: 01 Aug 2021, 06:01

Re: Create Screenshot specific area

Post by LAPIII » 08 Jun 2022, 23:04

Still the same thing happens. The image captures the screen far to the left of it.

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 08 Jun 2022, 23:08

All I can suggest is to make sure you close existing scripts and make sure you saved the changes before you run the new version. Maybe post your full script again.

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 08 Jun 2022, 23:11

Put a MsgBox line after it to check the coordinates like this:

Code: Select all

Area := X "|" Y "|" W "|" H
MsgBox, % Area

LAPIII
Posts: 668
Joined: 01 Aug 2021, 06:01

Re: Create Screenshot specific area

Post by LAPIII » 08 Jun 2022, 23:16

Now the script works fine, I probably didn't successfully reload, except for your last snippet. I tried on things other than that error dialogue. Thanks anyway, problem solved!

LAPIII
Posts: 668
Joined: 01 Aug 2021, 06:01

Re: Create Screenshot specific area

Post by LAPIII » 09 Jun 2022, 13:31

Some screenshots will sometimes contain the tooltip. Where can I add a delay to prevent this?

User avatar
boiler
Posts: 16950
Joined: 21 Dec 2014, 02:44

Re: Create Screenshot specific area

Post by boiler » 09 Jun 2022, 18:24

Nowhere. A delay isn’t the answer. Move the creation of the tooltip to after the call to the Screenshot function:

Code: Select all

!PrintScreen::
WinGetPos, X, Y, W, H, A
Area := X "|" Y "|" W "|" H
FormatTime, DateTime,, d-M-yy h-mm-ss tt
WinGetActiveTitle, Title
Screenshot(Title "_" DateTime ".png")
ToolTip, Active Window Screenshot, 1525, 0
SetTimer, RemoveToolTip, -500
return

User avatar
HiSoKa
Posts: 480
Joined: 27 Jan 2020, 15:43

Re: Create Screenshot specific area

Post by HiSoKa » 15 Dec 2022, 17:28

Hellbent wrote:
05 Apr 2022, 20:14
You can have a look through this and see if you find anything useful.
I wrote this a few years ago live on camera so obviously some improvements can be made to it but I have used it whenever I need to keep a screen cap on screen and haven't had any issues with it.

Code: Select all

;Written By: Hellbent
;Date Started: Dec 6th, 2019
;Date of Last Edit: Dec 7th, 2019
;Name: Screen Clipper
;Inspired by the screen clipping tool by Joe Glines.
;Pastebin Save: https://pastebin.com/fSErF35q  (last save)

;User Defined Values
;************************************************
Hotkey, RALT , CreateCapWindow , On  ;<------------------    Adjust the hotkey value to suit your needs / wants 
;************************************************
SaveToFile := 1 		 		   		;<------------------    Set this to 1 to save all clips with a unique name , Set it to 0 to overwrite the saved clip every time a new clip is made.
;************************************************
ShowCloseButton := 1 			   		;<------------------    Set this to 1 to show a small close button in the top right corner of the clip. Set this to 0 to keep the close button, but not show it.
;************************************************

#SingleInstance, Force  ; Force the script to close any other instances of this script. (Run one copy at a time)
SetBatchLines, -1 ;Set the script to run at top speed.
CoordMode, Mouse , Screen ;Use the screen as the refrence to get positions from.

IfNotExist, %A_ScriptDir%\Saved Clips ; if there is no folder for saved clips
	FileCreateDir, %A_ScriptDir%\Saved Clips ; create the folder.
SetWorkingDir, %A_ScriptDir%\Saved Clips ;Set the saved clips folder as the working dir.

Handles := [] ; Create an array to hold the name of the different gui's.
Index := 0 ;Used as the name of the current gui cap window.
return   ; End of Auto-Execute Section.

;**************************************************************************************
;**************************************************************************************
*^ESC::	ExitApp ; Hotkey to exit the script.
;**************************************************************************************
;**************************************************************************************

CloseClip: ;Close (Destroy this gui)
	hwnd := WinActive() ;Get the handle to the active window
	Gui, % Handles[ hwnd ] ": Destroy"  ;Destroy the gui with the name stored in the Handles array at position hwnd.
	return

MoveWindow: 
	PostMessage, 0xA1 , 2  ;Move the active window
	return

CreateCapWindow: ;Create a gui to used for setting the screen cap area and to display the resulting screen shot.
	Index++ ;Increment the current index. (the gui's name)
	Gui, %Index% : New , +AlwaysOnTop -Caption -DPIScale +ToolWindow +LastFound +Border hwndHwnd ;Create a new gui and set its options.
	Handles[hwnd] := Index  ;Use the windows handle (hwnd) as the index for the the value of the windows name. 
	Gui, %Index% : Color , 123456 ;Set the color of the gui (This color will be made transparent in the next step)
	WinSet, TransColor , 123456 ;Set only this color as transparent
	Gui, %Index% : Font, cMaroon s10 Bold Q5 , Segoe UI ;Set this gui's font. (Used for the close button)
	Active := 1
	ToolTip, Click and drag to set capture area. ;Display a tooltip that tells the user what to do.
	SetTimer, Tooltips , 30 ;Set a timer to move the tooltip around with the users cursor.
	return

Tooltips:
	ToolTip, Click and drag to set capture area. ;Display a tooltip that tells the user what to do.
	return

DrawCapArea:
	MouseGetPos, EX , EY ;Get the current position of the cursor.
	if( SX <= EX && SY <= EY )  ;If the current position is below and to the right of the starting position.
		WinPos := { X: SX , Y: SY , W: EX - SX , H: EY - SY } ;Create a object to hold the windows positions.
	else if( SX > EX && SY <= EY ) ;If the current position is below and to the left of the starting position.
		WinPos := { X: EX , Y: SY , W: SX - EX , H: EY - SY } ;Create a object to hold the windows positions.
	else if( SX <= EX && SY > EY ) ;If the current position is above and to the right of the starting position.
		WinPos := { X: SX , Y: EY , W: EX - SX , H: SY - EY } ;Create a object to hold the windows positions.
	else if( SX > EX && SY > EY ) ;If the current position is above and to the left of the starting position.
		WinPos := { X: EX , Y: EY , W: SX - EX , H: SY - EY } ;Create a object to hold the windows positions.
	Gui, %Index% : Show , % "x" WinPos.X " y" WinPos.Y " w" WinPos.W " h" WinPos.H " NA" ;Show the window in the correct position.
	return

TakeScreenShot:
	pToken := Gdip_Startup() ;Start using Gdip
	ClipBitmap := Gdip_BitmapFromScreen( WinPos.X "|" WinPos.Y "|" WinPos.W "|" WinPos.H ) ;Create a bitmap of the screen.
	
	Gdip_SaveBitmapToFile( ClipBitmap , A_WorkingDir "\" ( ( SaveToFile = 1 ) ? ( ClipName := "Saved Clip " A_Now ) : ( ClipName := "Temp Clip" ) ) ".png" , 100 ) ; Save the bitmap to file
	Gdip_DisposeImage( ClipBitmap ) ;Dispose of the bitmap to free memory.
	Gdip_Shutdown( pToken ) ;Turn off gdip
	return

#If (Active) ;Context sensitive hotkeys.

LButton::
	MouseGetPos, SX , SY ;Get the x and y starting position.
	SetTimer, DrawCapArea , 30 ;Set a timer for drawing a rectangle around the capture area.
	gosub, DrawCapArea ;Run the DrawCapArea routine immediately 
	return

LButton Up::
	Active := 0 ;Set context hotkeys off
	SetTimer, DrawCapArea , Off ;Turn off the drawing timer.
	SetTimer, Tooltips , Off ;Turn off the tooltips timer
	ToolTip, ;Turn off any tooltips.
	if( WinPos.W < 10 || WinPos.H < 10 ) { ; if the cap area width or height is less than 10px.
		Gui, %Index% : Destroy ;Destroy the gui
		return ; Skip taking a screen clip.
	}
	Gui, %Index% : -Border ;Remove the border before taking the screen clip
	gosub, TakeScreenShot ;Take a screen shot of the cap area.
	Gui, %Index% : +Border +LastFound ;Add the border again and Set the window as "LastFound" to use winset to turn off the transcolor a few lines down
	Gui, %Index% : Add , Text , % ( ( ShowCloseButton ) ? ( " Center 0x200 Border " ) : ( "" ) ) " x" WinPos.W - 20 " y0 w20 h20 BackgroundTrans gCloseClip" , % ( ( ShowCloseButton ) ? ( "X" ) : ( "" ) ) ;Create a trigger used for closing this window.
	Gui, %Index% : Add , Text , % "x0 y0 w" WinPos.W " h" WinPos.H " BackgroundTrans gMoveWindow" ;Create a trigger used for moving the window around.
	Gui, %Index% : Add , Picture , % "x0 y0 w" WinPos.W " h" WinPos.H ,% ClipName ".png"   ;Add the Screen clip image
	WinSet, TransColor , Off ;Turn off the transcolr setting.
	return
	
RButton::  ;If the right mouse button is pressed while selecting the screen clip area, Cancel the action and restore variables etc.
	Active := 0 ;Set context hotkeys off
	SetTimer, DrawCapArea , Off ;Turn off the drawing timer.
	SetTimer, Tooltips , Off ;Turn off the tooltips timer
	ToolTip, ;Turn off any tooltips.
	Gui, %Index% : Destroy ;Destroy the current gui
	return
	
#If

;******************************************************************************************************************************************
;******************************************************************************************************************************************
;***************************************************      GDIP Functions      *************************************************************
;******************************************************************************************************************************************
;******************************************************************************************************************************************
;From the GDIP lib by TIC
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_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_DisposeImage(pBitmap){
   return DllCall("gdiplus\GdipDisposeImage", A_PtrSize ? "UPtr" : "UInt", pBitmap)
}
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
}
GetDCEx(hwnd, flags=0, hrgnClip=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
    return DllCall("GetDCEx", Ptr, hwnd, Ptr, hrgnClip, "int", flags)
}
CreateCompatibleDC(hdc=0){
   return DllCall("CreateCompatibleDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
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
}
SelectObject(hdc, hgdiobj){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("SelectObject", Ptr, hdc, Ptr, hgdiobj)
}
GetDC(hwnd=0){
	return DllCall("GetDC", A_PtrSize ? "UPtr" : "UInt", hwnd)
}
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)
}
ReleaseDC(hdc, hwnd=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	return DllCall("ReleaseDC", Ptr, hwnd, Ptr, hdc)
}
Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0){
	Ptr := A_PtrSize ? "UPtr" : "UInt"
	DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", Ptr, hBitmap, Ptr, Palette, A_PtrSize ? "UPtr*" : "uint*", pBitmap)
	return pBitmap
}
DeleteObject(hObject){
   return DllCall("DeleteObject", A_PtrSize ? "UPtr" : "UInt", hObject)
}
DeleteDC(hdc){
   return DllCall("DeleteDC", A_PtrSize ? "UPtr" : "UInt", hdc)
}
Hello, @Hellbent ,
Thank you for this great code.
But a question please, How can I create another hotkey to make a screenshot for full screen with the CreateCapWindow GUI that appears after capture...
Last edited by HiSoKa on 16 Dec 2022, 00:21, edited 1 time in total.

Post Reply

Return to “Ask for Help (v1)”