Snipper - Window Snipping Tool
Re: Snipper - Window Snipping Tool
Thank you. There is nothing to miss except the ability to paint the selected screen area in V1.
Re: Snipper - Window Snipping Tool
I would also like some kind of brush, pen, paint, or anything that marks the snipped image.
It would be much easier to use something like this rather than Windows Paint in many cases.
FG, do you consider implementing anything of this kind in the future?
It would be much easier to use something like this rather than Windows Paint in many cases.
FG, do you consider implementing anything of this kind in the future?
- Thoughtfu1Tux
- Posts: 125
- Joined: 31 May 2018, 23:26
Re: Snipper - Window Snipping Tool
Anyone else run into the following code error randomly when trying to take a snip? I can't seem to figure out the cause of it.
Code: Select all
Error: This variable has not been assigned a value.
Specifically: static W
346: Return { X: X, Y: Y, W: W, H: H, X2: X + W, Y2: Y + H }
349: {
▶ 350: If GetKeyState('Shift', 'P') or DisplayWH and (W > 60 and H > 35)
351: {
352: guiSSR.GetPos(&X, &Y, &W, &H)
- FanaticGuru
- Posts: 1945
- Joined: 30 Sep 2013, 22:25
Re: Snipper - Window Snipping Tool
Thoughtfu1Tux wrote: ↑23 Sep 2023, 13:02Anyone else run into the following code error randomly when trying to take a snip? I can't seem to figure out the cause of it.
Code: Select all
Error: This variable has not been assigned a value. Specifically: static W 346: Return { X: X, Y: Y, W: W, H: H, X2: X + W, Y2: Y + H } 349: { ▶ 350: If GetKeyState('Shift', 'P') or DisplayWH and (W > 60 and H > 35) 351: { 352: guiSSR.GetPos(&X, &Y, &W, &H)
I am not sure how the script could get to this line without having already defined W and H but you can give them a default value in the Static line just to make sure.
For me it is line 229 (can vary due to Extensions).
Change: Static guiSSR, guiInfoDialog, DisplayWH := true, X, Y, W, H
To: Static guiSSR, guiInfoDialog, DisplayWH := true, X, Y, W := 0, H := 0
Let me know if this solves your problem and I will make the change in the OP of the script.
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
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
Re: Snipper - Window Snipping Tool
@FanaticGuru
Hello how can i Snipping with Visible rectangle, because i can't see the border.
Thanks
Hello how can i Snipping with Visible rectangle, because i can't see the border.
Thanks
Re: Snipper - Window Snipping Tool
@FanaticGuru
Sorry,
it's ok.
Sorry,
it's ok.
Re: Snipper - Window Snipping Tool
I added a new small return wrapper for the Ocr plugin.
I adapted the text detected with Ocr to @teadrinkerin Translate library. viewtopic.php?f=6&t=63835
I designed a simple gui for previewing without copying to the clipboard.
This is also how you can use teadrinker's Translate library:
It will translate the text read with Ocr into the specified language.
Simple Gui that I made to view and edit without copying to clipboard:
Status of Added Plugins:
I adapted the text detected with Ocr to @teadrinkerin Translate library. viewtopic.php?f=6&t=63835
I designed a simple gui for previewing without copying to the clipboard.
Code: Select all
; Snipper - Extension - OCR
; Version: 2023 05 05
Extensions.Push({ OCR1: { Text: 'Copy: Clipboard with OCR ', Func: OCR2Clipboard } })
Extensions.Push({ OCR1: { Text: 'Show: View with Ocr', Func: OCR2ToView } })
You need to use the already existing OCR2Clipboard plugin. I just added the OCR2ToReturn and OCR2ToView wrappers.
OCR2Clipboard(Borders := false)
{
; Get Hwnd of Active Snip
Hwnd := WinGetID('A')
; Get hBitMap of Snip
hBitMap := SendMessage(0x173, 0, 0, guiSnips[Hwnd].GuiObj.Pic)
; OCR of hBitMap
Result := OCR.FromBitmap(hBitMap)
; Put Result.Text on Clipboard
A_Clipboard := Result.Text
}
OCR2ToView(Borders := false)
{
; Get Hwnd of Active Snip
Hwnd := WinGetID('A')
; Get hBitMap of Snip
hBitMap := SendMessage(0x173, 0, 0, guiSnips[Hwnd].GuiObj.Pic)
; OCR of hBitMap
Result := OCR.FromBitmap(hBitMap)
; Put Result.Text on Clipboard
TextShowGuiFnc(Result.Text)
}
OCR2ToReturn(Borders := false)
{
; Get Hwnd of Active Snip
Hwnd := WinGetID('A')
; Get hBitMap of Snip
hBitMap := SendMessage(0x173, 0, 0, guiSnips[Hwnd].GuiObj.Pic)
; OCR of hBitMap
Result := OCR.FromBitmap(hBitMap)
; Put Result.Text on Clipboard
Return Result.Text
}
/** https://github.com/Descolada/OCR
* OCR library: a wrapper for the the UWP Windows.Media.Ocr library.
* Based on the UWP OCR function for AHK v1 by malcev.
*
* Ways of initiating OCR:
* OCR(IRandomAccessStream, lang?)
* OCR.FromDesktop(lang?, scale:=1)
* OCR.FromRect(X, Y, W, H, lang?, scale:=1)
* OCR.FromWindow(WinTitle?, lang?, scale:=1, onlyClientArea:=0, mode:=2)
* OCR.FromFile(FileName, lang?)
* OCR.FromBitmap(HBitmap, lang?)
*
* Additional methods:
* OCR.GetAvailableLanguages()
* OCR.LoadLanguage(lang:="FirstFromAvailableLanguages")
* OCR.WaitText(needle, timeout:=-1, func?, casesense:=False, comparefunc?)
* Calls a func (the provided OCR method) until a string is found
* OCR.WordsBoundingRect(words*)
* Returns the bounding rectangle for multiple words
*
* Properties:
* OCR.MaxImageDimension
* MinImageDimension is not documented, but appears to be 40 pixels (source: user FanaticGuru in AutoHotkey forums)
*
* OCR returns an OCR results object:
* Result.Text => All recognized text
* Result.TextAngle => Clockwise rotation of the recognized text
* Result.Lines => Array of all Line objects
* Result.Words => Array of all Word objects
* Result.ImageWidth => Used image width
* Result.ImageHeight => Used image height
*
* Result.FindString(needle, i:=1, casesense:=False, wordCompareFunc?)
* Finds a string in the result
* Result.Click(Obj, WhichButton?, ClickCount?, DownOrUp?)
* Clicks an object (Word, FindString result etc)
* Result.ControlClick(obj, WinTitle?, WinText?, WhichButton?, ClickCount?, Options?, ExcludeTitle?, ExcludeText?)
* ControlClicks an object (Word, FindString result etc)
* Result.Highlight(obj?, showTime:=2000, color:="Red", d:=2)
* Highlights an object on the screen, or removes the highlighting
*
*
* Line object:
* Line.Text => Recognized text of the line
* Line.Words => Array of Word objects for the Line
*
* Word object:
* Line.Text => Recognized text of the word
* Line.x,y,w,h => Size and location of the Word. Coordinates are relative to the original image.
* Line.BoundingRect => Bounding rectangle of the Word in format {x,y,w,h}. Coordinates are relative to the original image.
*
* Additional notes:
* Languages are recognized in BCP-47 language tags. Eg. OCR.FromFile("myfile.bmp", "en-AU")
* Languages can be installed for example with PowerShell (run as admin): Install-Language <language-tag>
* or from Language settings in Settings.
* Not all language packs support OCR though. A list of supported language can be gotten from
* Powershell (run as admin) with the following command: Get-WindowsCapability -Online | Where-Object { $_.Name -Like 'Language.OCR*' }
*/
class OCR {
static IID_IRandomAccessStream := "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}"
, IID_IPicture := "{7BF80980-BF32-101A-8BBB-00AA00300CAB}"
, IID_IAsyncInfo := "{00000036-0000-0000-C000-000000000046}"
class IBase {
__New(ptr?) {
if IsSet(ptr) && !ptr
throw ValueError('Invalid IUnknown interface pointer', -2, this.__Class)
this.DefineProp("ptr", {Value:ptr ?? 0})
}
__Delete() => this.ptr ? ObjRelease(this.ptr) : 0
}
static __New() {
this.LanguageFactory := OCR.CreateClass("Windows.Globalization.Language", ILanguageFactory := "{9B0252AC-0C27-44F8-B792-9793FB66C63E}")
this.BitmapEncoderStatics := OCR.CreateClass("Windows.Graphics.Imaging.BitmapEncoder", IBitmapEncoderStatics := "{A74356A7-A4E4-4EB9-8E40-564DE7E1CCB2}")
this.BitmapDecoderStatics := OCR.CreateClass("Windows.Graphics.Imaging.BitmapDecoder", IBitmapDecoderStatics := "{438CCB26-BCEF-4E95-BAD6-23A822E58D01}")
this.OcrEngineStatics := OCR.CreateClass("Windows.Media.Ocr.OcrEngine", IOcrEngineStatics := "{5BFFA85A-3384-3540-9940-699120D428A8}")
ComCall(6, this.OcrEngineStatics, "uint*", &MaxImageDimension:=0) ; MaxImageDimension
this.MaxImageDimension := MaxImageDimension
}
/**
* Returns an OCR results object for an IRandomAccessStream.
* Images of other types should be first converted to this format (eg from file, from bitmap).
* @param pIRandomAccessStream Pointer or an object containing a ptr to the stream
* @param {String} lang OCR language. Default is first from available languages.
* @returns {Ocr}
*/
__New(pIRandomAccessStream?, lang := "FirstFromAvailableLanguages") {
if IsSet(lang) || !OCR.HasOwnProp("CurrentLanguage")
OCR.LoadLanguage(lang?)
ComCall(14, OCR.BitmapDecoderStatics, "ptr", pIRandomAccessStream, "ptr*", BitmapDecoder:=OCR.IBase()) ; CreateAsync
OCR.WaitForAsync(&BitmapDecoder)
BitmapFrame := ComObjQuery(BitmapDecoder, IBitmapFrame := "{72A49A1C-8081-438D-91BC-94ECFC8185C6}")
ComCall(12, BitmapFrame, "uint*", &width:=0) ; get_PixelWidth
ComCall(13, BitmapFrame, "uint*", &height:=0) ; get_PixelHeight
if (width > OCR.MaxImageDimension) or (height > OCR.MaxImageDimension)
throw ValueError("Image is too big - " width "x" height ".`nIt should be maximum - " OCR.MaxImageDimension " pixels")
BitmapFrameWithSoftwareBitmap := ComObjQuery(BitmapDecoder, IBitmapFrameWithSoftwareBitmap := "{FE287C9A-420C-4963-87AD-691436E08383}")
if width < 40 || height < 40 {
BitmapTransform := OCR.CreateClass("Windows.Graphics.Imaging.BitmapTransform")
scale := 40.0 / Min(width, height), this.ImageWidth := Ceil(width*scale), this.ImageHeight := Ceil(height*scale)
ComCall(7, BitmapTransform, "int", this.ImageWidth) ; put_ScaledWidth
ComCall(9, BitmapTransform, "int", this.ImageHeight) ; put_ScaledHeight
ComCall(8, BitmapFrame, "uint*", &BitmapPixelFormat:=0) ; get_BitmapPixelFormat
ComCall(9, BitmapFrame, "uint*", &BitmapAlphaMode:=0) ; get_BitmapAlphaMode
ComCall(8, BitmapFrameWithSoftwareBitmap, "uint", BitmapPixelFormat, "uint", BitmapAlphaMode, "ptr", BitmapTransform, "uint", IgnoreExifOrientation := 0, "uint", DoNotColorManage := 0, "ptr*", SoftwareBitmap:=OCR.IBase()) ; GetSoftwareBitmapAsync
} else {
this.ImageWidth := width, this.ImageHeight := height
ComCall(6, BitmapFrameWithSoftwareBitmap, "ptr*", SoftwareBitmap:=OCR.IBase()) ; GetSoftwareBitmapAsync
}
OCR.WaitForAsync(&SoftwareBitmap)
ComCall(6, OCR.OcrEngine, "ptr", SoftwareBitmap, "ptr*", OcrResult:=OCR.IBase()) ; RecognizeAsync
OCR.WaitForAsync(&OcrResult)
; Cleanup
OCR.CloseIClosable(pIRandomAccessStream)
OCR.CloseIClosable(SoftwareBitmap)
this.ptr := OcrResult.ptr, ObjAddRef(OcrResult.ptr)
}
__Delete() => this.ptr ? ObjRelease(this.ptr) : 0
; Gets the recognized text.
Text {
get {
ComCall(8, this, "ptr*", &hAllText:=0) ; get_Text
buf := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hAllText, "uint*", &length:=0, "ptr")
this.DefineProp("Text", {Value:StrGet(buf, "UTF-16")})
OCR.DeleteHString(hAllText)
return this.Text
}
}
; Gets the clockwise rotation of the recognized text, in degrees, around the center of the image.
TextAngle {
get => (ComCall(7, this, "double*", &value:=0), value)
}
; Returns all Line objects for the result.
Lines {
get {
ComCall(6, this, "ptr*", LinesList:=OCR.IBase()) ; get_Lines
ComCall(7, LinesList, "int*", &count:=0) ; count
lines := []
loop count {
ComCall(6, LinesList, "int", A_Index-1, "ptr*", OcrLine:=OCR.OCRLine())
lines.Push(OcrLine)
}
this.DefineProp("Lines", {Value:lines})
return lines
}
}
; Returns all Word objects for the result. Equivalent to looping over all the Lines and getting the Words.
Words {
get {
words := []
for line in this.Lines
for word in line.Words
words.Push(word)
this.DefineProp("Words", {Value:words})
return words
}
}
/**
* Clicks an object
* @param Obj The object to click, which can be a OCR result object, Line, Word, or Object {x,y,w,h}
* If this object (the one Click is called from) contains a "Relative" property (this is
* added by default with OCR.FromWindow) containing a Hwnd property, then that window will be activated,
* otherwise the Relative properties values will be added to the x and y coordinates as offsets.
*/
Click(Obj, WhichButton?, ClickCount?, DownOrUp?) {
if !obj.HasOwnProp("x") && InStr(Type(obj), "OCR")
obj := OCR.WordsBoundingRect(obj.Words)
x := obj.x, y := obj.y, w := obj.w, h := obj.h
if this.HasOwnProp("Relative") {
if this.Relative.HasOwnProp("Hwnd") {
if !WinActive(this.Relative.Hwnd) {
WinActivate(this.Relative.Hwnd)
WinWaitActive(this.Relative.Hwnd,,1)
}
} else
x += this.Relative.x, y += this.Relative.y
}
oldCoordMode := A_CoordModeMouse
CoordMode "Mouse", this.HasOwnProp("Relative") && this.Relative.HasOwnProp("Type") ? this.Relative.Type : "Screen"
Click(x+w//2, y+h//2, WhichButton?, ClickCount?, DownOrUp?)
CoordMode "Mouse", oldCoordMode
}
/**
* ControlClicks an object
* @param obj The object to click, which can be a OCR result object, Line, Word, or Object {x,y,w,h}
* If this object (the one Click is called from) contains a "Relative" property (this is
* added by default with OCR.FromWindow) containing a Hwnd property, then that window will be activated,
* otherwise the Relative properties values will be added to the x and y coordinates as offsets.
* @param WinTitle If WinTitle is set, then the coordinates stored in Obj will be converted to
* client coordinates and ControlClicked.
*/
ControlClick(obj, WinTitle?, WinText?, WhichButton?, ClickCount?, Options?, ExcludeTitle?, ExcludeText?) {
if !obj.HasOwnProp("x") && InStr(Type(obj), "OCR")
obj := OCR.WordsBoundingRect(obj.Words)
x := obj.x, y := obj.y, w := obj.w, h := obj.h
if this.HasOwnProp("Relative") && this.Relative.HasOwnProp("Type") {
hWnd := this.Relative.hWnd
if this.Relative.Type = "Window" {
; Window -> Client
RECT := Buffer(16, 0), pt := Buffer(8, 0)
DllCall("user32\GetWindowRect", "Ptr", hWnd, "Ptr", RECT)
winX := NumGet(RECT, 0, "Int"), winY := NumGet(RECT, 4, "Int")
NumPut("int", winX+x, "int", winY+y, pt)
DllCall("user32\ScreenToClient", "Ptr", hWnd, "Ptr", pt)
x := NumGet(pt,0,"int"), y := NumGet(pt,4,"int")
}
} else if IsSet(WinTitle) {
hWnd := WinExist(WinTitle, WinText?, ExcludeTitle?, ExcludeText?)
pt := Buffer(8), NumPut("int",x,pt), NumPut("int", y,pt,4)
DllCall("ScreenToClient", "Int", Hwnd, "Ptr", pt)
x := NumGet(pt,0,"int"), y := NumGet(pt,4,"int")
} else
throw TargetError("ControlClick needs to be called either after a OCR.FromWindow result or with a WinTitle argument")
ControlClick("X" (x+w//2) " Y" (y+h//2), hWnd,, WhichButton?, ClickCount?, Options?)
}
/**
* Highlights an object on the screen with a red box
* @param obj The object to highlight. which can be a OCR result object, Line, Word, or Object {x,y,w,h}
* If this object (the one Highlight is called from) contains a "Relative" property (this is
* added by default with OCR.FromWindow), then its values will be added to the x and y coordinates as offsets.
* @param {number} showTime Default is 2 seconds.
* * Unset - if highlighting exists then removes the highlighting
* * 0 - Indefinite highlighting
* * Positive integer (eg 2000) - will highlight and pause for the specified amount of time in ms
* * Negative integer - will highlight for the specified amount of time in ms, but script execution will continue
* @param {string} color The color of the highlighting. Default is red.
* @param {number} d The border thickness of the highlighting in pixels. Default is 2.
* @returns {OCR}
*/
Highlight(obj?, showTime:=2000, color:="Red", d:=2) {
static guis := []
if !IsSet(obj) {
for _, r in guis
r.Destroy()
guis := []
return this
}
if !guis.Length {
Loop 4
guis.Push(Gui("+AlwaysOnTop -Caption +ToolWindow -DPIScale +E0x08000000"))
}
if Type(obj) = "OCR.OCRLine" || Type(obj) = "OCR"
obj := OCR.WordsBoundingRect(obj.Words*)
x := obj.x, y := obj.y, w := obj.w, h := obj.h
if this.HasOwnProp("Relative")
x += this.Relative.x, y += this.Relative.y
Loop 4 {
i:=A_Index
, x1:=(i=2 ? x+w : x-d)
, y1:=(i=3 ? y+h : y-d)
, w1:=(i=1 or i=3 ? w+2*d : d)
, h1:=(i=2 or i=4 ? h+2*d : d)
guis[i].BackColor := color
guis[i].Show("NA x" . x1 . " y" . y1 . " w" . w1 . " h" . h1)
}
if showTime > 0 {
Sleep(showTime)
this.Highlight()
} else if showTime < 0
SetTimer(this.GetMethod("Highlight"), -Abs(showTime))
return this
}
/**
* Finds a string in the search results. Returns {x,y,w,h,Words} where Words contains an array of the matching Word objects.
* @param needle The string to find
* @param {number} i Which occurrence of needle to find
* @param {number} casesense Comparison case-sensitivity. Default is False/Off.
* @param wordCompareFunc Optionally a custom word comparison function. Accepts two arguments,
* neither of which should contain spaces
* @returns {Object}
*/
FindString(needle, i:=1, casesense:=False, wordCompareFunc?) {
splitNeedle := StrSplit(RegExReplace(needle, " +", " "), " "), needleLen := splitNeedle.Length
if !IsSet(wordCompareFunc)
wordCompareFunc := casesense ? ((arg1, arg2) => arg1 == arg2) : ((arg1, arg2) => arg1 = arg2)
for line in this.Lines {
if InStr(l := line.Text, needle, casesense) {
counter := 0, found := []
for word in line.Words {
t := word.Text, len := StrLen(t)
if wordCompareFunc(splitNeedle[found.Length+1], t) {
found.Push(word)
if found.Length == needleLen {
if ++counter == i {
result := OCR.WordsBoundingRect(found*)
result.Words := found
return result
} else
found := []
}
} else
found := []
}
}
}
throw TargetError('The target string "' needle '" was not found', -1)
}
class OCRLine extends OCR.IBase {
; Gets the recognized text for the line.
Text {
get {
ComCall(7, this, "ptr*", &hText:=0) ; get_Text
buf := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hText, "uint*", &length:=0, "ptr")
text := StrGet(buf, "UTF-16")
OCR.DeleteHString(hText)
this.DefineProp("Text", {Value:text})
return text
}
}
; Gets the Word objects for the line
Words {
get {
ComCall(6, this, "ptr*", WordsList:=OCR.IBase()) ; get_Words
ComCall(7, WordsList, "int*", &WordsCount:=0) ; Words count
words := []
loop WordsCount {
ComCall(6, WordsList, "int", A_Index-1, "ptr*", OcrWord:=OCR.OCRWord())
words.Push(OcrWord)
}
this.DefineProp("Words", {Value:words})
return words
}
}
}
class OCRWord extends OCR.IBase {
; Gets the recognized text for the word
Text {
get {
ComCall(7, this, "ptr*", &hText:=0) ; get_Text
buf := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hText, "uint*", &length:=0, "ptr")
text := StrGet(buf, "UTF-16")
OCR.DeleteHString(hText)
this.DefineProp("Text", {Value:text})
return text
}
}
/**
* Gets the bounding rectangle of the text in {x,y,w,h} format.
* The bounding rectangles coordinate system will be dependant on the image capture method.
* For example, if the image was captured as a rectangle from the screen, then the coordinates
* will be relative to the left top corner of the rectangle.
*/
BoundingRect {
get {
ComCall(6, this, "ptr", RECT := Buffer(16, 0)) ; get_BoundingRect
this.DefineProp("x", {Value:Integer(NumGet(RECT, 0, "float"))})
, this.DefineProp("y", {Value:Integer(NumGet(RECT, 4, "float"))})
, this.DefineProp("w", {Value:Integer(NumGet(RECT, 8, "float"))})
, this.DefineProp("h", {Value:Integer(NumGet(RECT, 12, "float"))})
return this.DefineProp("BoundingRect", {Value:{x:this.x, y:this.y, w:this.w, h:this.h}}).BoundingRect
}
}
x {
get => this.BoundingRect.x
}
y {
get => this.BoundingRect.y
}
w {
get => this.BoundingRect.w
}
h {
get => this.BoundingRect.h
}
}
/**
* Returns an OCR results object for an image file. Locations of the words will be relative to
* the top left corner of the image.
* @param FileName Either full or relative (to A_ScriptDir) path to the file.
* @param lang OCR language. Default is first from available languages.
* @returns {Ocr}
*/
static FromFile(FileName, lang?) {
if (SubStr(FileName, 2, 1) != ":")
FileName := A_ScriptDir "\" FileName
if !FileExist(FileName) or InStr(FileExist(FileName), "D")
throw TargetError("File `"" FileName "`" doesn't exist", -1)
GUID := OCR.CLSIDFromString(OCR.IID_IRandomAccessStream)
DllCall("ShCore\CreateRandomAccessStreamOnFile", "wstr", FileName, "uint", Read := 0, "ptr", GUID, "ptr*", IRandomAccessStream:=OCR.IBase())
return OCR(IRandomAccessStream, lang?)
}
/**
* Returns an OCR results object for a given window. Locations of the words will be relative to the
* window or client area, so for interactions use CoordMode "Window" or "Client".
* @param WinTitle A window title or other criteria identifying the target window.
* @param lang OCR language. Default is first from available languages.
* @param scale The scaling factor to use.
* @param {Number} onlyClientArea Whether only the client area or the whole window should be OCR-d
* @param {Number} mode Different methods of capturing the window. 0 = uses GetDC with BitBlt, 2 = uses PrintWindow.
* Add 1 to make a transparent window totally opaque.
* @returns {Ocr}
*/
static FromWindow(WinTitle:="", lang?, scale:=1, onlyClientArea:=0, mode:=2) {
if !(hWnd := WinExist(WinTitle))
throw TargetError("Target window not found", -1)
if DllCall("IsIconic", "uptr", hwnd)
DllCall("ShowWindow", "uptr", hwnd, "int", 4)
if mode&1 {
oldStyle := WinGetExStyle(hwnd), i := 0
WinSetTransparent(255, hwnd)
While (WinGetTransparent(hwnd) != 255 && ++i < 30)
Sleep 100
}
If onlyClientArea {
DllCall("GetClientRect", "ptr", hwnd, "ptr", rc:=Buffer(16))
W := NumGet(rc, 8, "int"), H := NumGet(rc, 12, "int")
pt:=Buffer(8, 0), NumPut("int64", 0, pt)
DllCall("ClientToScreen", "Ptr", hwnd, "Ptr", pt)
X:=NumGet(pt,"int"), Y:=NumGet(pt,4,"int")
} else {
rect := Buffer(16, 0)
DllCall("GetWindowRect", "UPtr", hwnd, "Ptr", rect, "UInt")
X := NumGet(rect, 0, "Int"), Y := NumGet(rect, 4, "Int")
x2 := NumGet(rect, 8, "Int"), y2 := NumGet(rect, 12, "Int")
W := Abs(Max(X, X2) - Min(X, X2))
H := Abs(Max(Y, Y2) - Min(Y, Y2))
}
hBitMap := OCR.CreateBitmap(X, Y, W, H, hWnd, scale, onlyClientArea, mode)
;OCR.DisplayHBitmap(hBitMap)
if mode&1
WinSetExStyle(oldStyle, hwnd)
result := OCR(OCR.HBitmapToRandomAccessStream(hBitMap), lang?)
result.Relative := {X:X, Y:Y, Type:(onlyClientArea ? "Client" : "Window"), Hwnd:hWnd}
OCR.NormalizeCoordinates(result, scale)
return result
}
/**
* Returns an OCR results object for the whole desktop. Locations of the words will be relative to
* the screen (CoordMode "Screen")
* @param lang OCR language. Default is first from available languages.
* @returns {Ocr}
*/
static FromDesktop(lang?, scale:=1) => OCR.FromRect(0, 0, A_ScreenWidth, A_ScreenHeight, lang?, scale)
/**
* Returns an OCR results object for a region of the screen. Locations of the words will be relative
* to the top left corner of the rectangle.
* @param x Screen x coordinate
* @param y Screen y coordinate
* @param w Region width. Maximum is OCR.MaxImageDimension; minimum is 40 pixels (source: user FanaticGuru in AutoHotkey forums), smaller images will be scaled to at least 40 pixels.
* @param h Region height. Maximum is OCR.MaxImageDimension; minimum is 40 pixels, smaller images will be scaled accordingly.
* @param lang OCR language. Default is first from available languages.
* @param scale The scaling factor to use. Larger number (eg 2) might improve the accuracy
* of the OCR, at the cost of speed.
* @returns {Ocr}
*/
static FromRect(x, y, w, h, lang?, scale:=1) {
hBitmap := OCR.CreateBitmap(X, Y, W, H,,scale)
result := OCR(OCR.HBitmapToRandomAccessStream(hBitmap), lang?)
result.Relative := {x:x, y:y}
return OCR.NormalizeCoordinates(result, scale)
}
/**
* Returns an OCR results object from a hBitmap object. Locations of the words will be relative
* to the top left corner of the bitmap.
* @param hBitmap An hBitmap pointer or an object with a ptr property
* @param lang OCR language. Default is first from available languages.
* @returns {ocr}
*/
static FromBitmap(hBitmap, lang?) => OCR(OCR.HBitmapToRandomAccessStream(hBitmap), lang?)
/**
* Returns all available languages as a string, where the languages are separated by newlines.
* @returns {String}
*/
static GetAvailableLanguages() {
static GlobalizationPreferencesStatics
if !IsSet(GlobalizationPreferencesStatics)
GlobalizationPreferencesStatics := OCR.CreateClass("Windows.System.UserProfile.GlobalizationPreferences", IGlobalizationPreferencesStatics := "{01BF4326-ED37-4E96-B0E9-C1340D1EA158}")
ComCall(9, GlobalizationPreferencesStatics, "ptr*", &LanguageList:=0) ; get_Languages
ComCall(7, LanguageList, "int*", &count:=0) ; count
Loop count {
ComCall(6, LanguageList, "int", A_Index-1, "ptr*", &hString:=0) ; get_Item
ComCall(6, this.LanguageFactory, "ptr", hString, "ptr*", &LanguageTest:=0) ; CreateLanguage
ComCall(8, this.OcrEngineStatics, "ptr", LanguageTest, "int*", &bool:=0) ; IsLanguageSupported
if (bool = 1) {
ComCall(6, LanguageTest, "ptr*", &hText:=0)
buf := DllCall("Combase.dll\WindowsGetStringRawBuffer", "ptr", hText, "uint*", &length:=0, "ptr")
text .= StrGet(buf, "UTF-16") "`n"
}
ObjRelease(LanguageTest)
}
ObjRelease(LanguageList)
return text
}
/**
* Loads a new language which will be used with subsequent OCR calls.
* @param {string} lang OCR language. Default is first from available languages.
* @returns {void}
*/
static LoadLanguage(lang:="FirstFromAvailableLanguages") {
if this.HasOwnProp("CurrentLanguage") && this.HasOwnProp("OcrEngine") && this.CurrentLanguage = lang
return
if (lang = "FirstFromAvailableLanguages")
ComCall(10, this.OcrEngineStatics, "ptr*", OcrEngine:=OCR.IBase()) ; TryCreateFromUserProfileLanguages
else {
hString := OCR.CreateHString(lang)
ComCall(6, this.LanguageFactory, "ptr", hString, "ptr*", Language:=OCR.IBase()) ; CreateLanguage
OCR.DeleteHString(hString)
ComCall(9, this.OcrEngineStatics, "ptr", Language, "ptr*", OcrEngine:=OCR.IBase()) ; TryCreateFromLanguage
}
if (OcrEngine.ptr = 0)
Throw Error("Can not use language `"" lang "`" for OCR, please install language pack.")
this.OcrEngine := OcrEngine, this.CurrentLanguage := lang
}
/**
* Returns a bounding rectangle {x,y,w,h} for the provided Word objects
* @param words Word object arguments (at least 1)
* @returns {Object}
*/
static WordsBoundingRect(words*) {
if !words.Length
throw ValueError("This function requires at least one argument")
X1 := 100000000, Y1 := 100000000, X2 := -100000000, Y2 := -100000000
for word in words {
X1 := Min(word.x, X1), Y1 := Min(word.y, Y1), X2 := Max(word.x+word.w, X2), Y2 := Max(word.y+word.h, Y2)
}
return {X:X1, Y:Y1, W:X2-X1, H:Y2-Y1, X2:X2, Y2:Y2}
}
/**
* Waits text to appear on screen. If the method is successful, then Func's return value is returned.
* Otherwise nothing is returned.
* @param needle The searched text
* @param {number} timeout Timeout in milliseconds. Less than 0 is indefinite wait (default)
* @param func The function to be called for the OCR. Default is OCR.FromDesktop
* @param casesense Text comparison case-sensitivity
* @param comparefunc A custom string compare/search function, that accepts two arguments: haystack and needle.
* Default is InStr. If a custom function is used, then casesense is ignored.
* @returns {OCR}
*/
static WaitText(needle, timeout:=-1, func?, casesense:=False, comparefunc?) {
endTime := A_TickCount+timeout
if !IsSet(func)
func := OCR.FromDesktop
if !IsSet(comparefunc)
comparefunc := InStr.Bind(,,casesense)
While timeout > 0 ? (A_TickCount < endTime) : 1 {
result := func()
if comparefunc(result.Text, needle)
return result
}
return
}
;; Only internal methods ahead
static CreateDIBSection(w, h, hdc?, bpp:=32, &ppvBits:=0) {
hdc2 := IsSet(hdc) ? hdc : DllCall("GetDC", "Ptr", 0, "UPtr")
bi := Buffer(40, 0)
NumPut("int", 40, "int", w, "int", h, "ushort", 1, "ushort", bpp, "int", 0, bi)
hbm := DllCall("CreateDIBSection", "uint", hdc2, "ptr" , bi, "uint" , 0, "uint*", &ppvBits:=0, "uint" , 0, "uint" , 0)
if !IsSet(hdc)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hdc2)
return hbm
}
static CreateBitmap(X, Y, W, H, hWnd := 0, scale:=1, onlyClientArea:=0, mode:=2) {
static CAPTUREBLT
if !IsSet(CAPTUREBLT) {
DllCall("Dwmapi\DwmIsCompositionEnabled", "Int*", &compositionEnabled:=0)
CAPTUREBLT:= compositionEnabled ? 0 : 0x40000000
}
sW := W*scale, sH := H*scale
if hWnd {
if mode < 2 {
X := 0, Y := 0
HDC := DllCall("GetDCEx", "Ptr", hWnd, "Ptr", 0, "int", 2|!onlyClientArea, "Ptr")
} else {
hbm := OCR.CreateDIBSection(W, H)
hdc := DllCall("CreateCompatibleDC", "Ptr", 0, "UPtr")
obm := DllCall("SelectObject", "Ptr", HDC, "Ptr", HBM)
DllCall("PrintWindow", "uint", hwnd, "uint", hdc, "uint", 2|!!onlyClientArea)
if scale != 1 {
PDC := DllCall("CreateCompatibleDC", "Ptr", HDC, "UPtr")
hbm2 := DllCall("CreateCompatibleBitmap", "Ptr", HDC, "Int", sW, "Int", sH, "UPtr")
DllCall("SelectObject", "Ptr", PDC, "Ptr", HBM2)
DllCall("StretchBlt", "Ptr", PDC, "Int", 0, "Int", 0, "Int", sW, "Int", sH, "Ptr", HDC, "Int", 0, "Int", 0, "Int", W, "Int", H, "UInt", 0x00CC0020 | CAPTUREBLT) ; SRCCOPY
DllCall("DeleteDC", "Ptr", PDC)
DllCall("DeleteObject", "UPtr", HBM)
hbm := hbm2
}
DllCall("DeleteDC", "Ptr", HDC)
return OCR.IBase(HBM).DefineProp("__Delete", {call:(*)=>DllCall("DeleteObject", "UPtr", HBM)})
}
} else {
HDC := DllCall("GetDC", "Ptr", 0, "UPtr")
}
HBM := DllCall("CreateCompatibleBitmap", "Ptr", HDC, "Int", Max(40,sW), "Int", Max(40,sH), "UPtr")
PDC := DllCall("CreateCompatibleDC", "Ptr", HDC, "UPtr")
DllCall("SelectObject", "Ptr", PDC, "Ptr", HBM)
if sW < 40 || sH < 40 ; Fills the bitmap so it's at least 40x40, which seems to improve recognition
DllCall("StretchBlt", "Ptr", PDC, "Int", 0, "Int", 0, "Int", Max(40,sW), "Int", Max(40,sH), "Ptr", HDC, "Int", X, "Int", Y, "Int", 1, "Int", 1, "UInt", 0x00CC0020 | CAPTUREBLT) ; SRCCOPY.
DllCall("StretchBlt", "Ptr", PDC, "Int", 0, "Int", 0, "Int", sW, "Int", sH, "Ptr", HDC, "Int", X, "Int", Y, "Int", W, "Int", H, "UInt", 0x00CC0020 | CAPTUREBLT) ; SRCCOPY
DllCall("DeleteDC", "Ptr", PDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", HDC)
return OCR.IBase(HBM).DefineProp("__Delete", {call:(*)=>DllCall("DeleteObject", "UPtr", HBM)})
}
static HBitmapToRandomAccessStream(hBitmap) {
static PICTYPE_BITMAP := 1
, BSOS_DEFAULT := 0
, sz := 8 + A_PtrSize*2
DllCall("Ole32\CreateStreamOnHGlobal", "Ptr", 0, "UInt", true, "Ptr*", pIStream:=OCR.IBase(), "UInt")
PICTDESC := Buffer(sz, 0)
NumPut("uint", sz, "uint", PICTYPE_BITMAP, "ptr", IsInteger(hBitmap) ? hBitmap : hBitmap.ptr, PICTDESC)
riid := OCR.CLSIDFromString(OCR.IID_IPicture)
DllCall("OleAut32\OleCreatePictureIndirect", "Ptr", PICTDESC, "Ptr", riid, "UInt", 0, "Ptr*", pIPicture:=OCR.IBase(), "UInt")
; IPicture::SaveAsFile
ComCall(15, pIPicture, "Ptr", pIStream, "UInt", true, "uint*", &size:=0, "UInt")
riid := OCR.CLSIDFromString(OCR.IID_IRandomAccessStream)
DllCall("ShCore\CreateRandomAccessStreamOverStream", "Ptr", pIStream, "UInt", BSOS_DEFAULT, "Ptr", riid, "Ptr*", pIRandomAccessStream:=OCR.IBase(), "UInt")
Return pIRandomAccessStream
}
static DisplayHBitmap(hBitmap, W:=640, H:=640) {
gImage := Gui()
hPic := gImage.Add("Text", "0xE w" W " h" H)
SendMessage(0x172, 0, hBitmap,, hPic.Hwnd)
gImage.Show()
WinWaitClose gImage
}
static CreateClass(str, interface?) {
hString := OCR.CreateHString(str)
if !IsSet(interface) {
result := DllCall("Combase.dll\RoActivateInstance", "ptr", hString, "ptr*", cls:=OCR.IBase(), "uint")
} else {
GUID := OCR.CLSIDFromString(interface)
result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", GUID, "ptr*", cls:=OCR.IBase(), "uint")
}
if (result != 0) {
if (result = 0x80004002)
throw Error("No such interface supported", -1, interface)
else if (result = 0x80040154)
throw Error("Class not registered", -1)
else
throw Error(result)
}
OCR.DeleteHString(hString)
return cls
}
static CreateHString(str) => (DllCall("Combase.dll\WindowsCreateString", "wstr", str, "uint", StrLen(str), "ptr*", &hString:=0), hString)
static DeleteHString(hString) => DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
static WaitForAsync(&obj) {
AsyncInfo := ComObjQuery(obj, OCR.IID_IAsyncInfo)
Loop {
ComCall(7, AsyncInfo, "uint*", &status:=0) ; IAsyncInfo.Status
if (status != 0) {
if (status != 1) {
ComCall(8, ASyncInfo, "uint*", &ErrorCode:=0) ; IAsyncInfo.ErrorCode
throw Error("AsyncInfo failed with status error " ErrorCode, -1)
}
break
}
Sleep 10
}
ComCall(8, obj, "ptr*", ObjectResult:=OCR.IBase()) ; GetResults
obj := ObjectResult
}
static CloseIClosable(pClosable) {
static IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}"
Close := ComObjQuery(pClosable, IClosable)
ComCall(6, Close) ; Close
if !IsObject(pClosable)
ObjRelease(pClosable)
}
static CLSIDFromString(IID) {
CLSID := Buffer(16)
if res := DllCall("ole32\CLSIDFromString", "WStr", IID, "Ptr", CLSID, "UInt")
throw Error("CLSIDFromString failed. Error: " . Format("{:#x}", res))
Return CLSID
}
static NormalizeCoordinates(result, scale) {
if scale != 1 {
for word in result.Words
word.x := Integer(word.x / scale), word.y := Integer(word.y / scale), word.w := Integer(word.w / scale), word.h := Integer(word.h / scale), word.BoundingRect := {X:word.x, Y:word.y, W:word.w, H:word.h}
}
return result
}
}
It will translate the text read with Ocr into the specified language.
Code: Select all
; Snipper - Extension - OCR
; Version: 2023 12 20
Extensions.Push({ Translate: { Text: 'Translate: Translate to Turkish', Func: GoogleTranslateWrapperToTr } })
Extensions.Push({ Translate: { Text: 'Translate: Translate to English', Func: GoogleTranslateWrapperToEn } })
GoogleTranslateWrapperToTr(Borders := false)
{
ocrReturn := OCR2ToReturn()
Translatetext := GoogleTranslate(ocrReturn, &from := 'auto',"tr")
;MsgBox 'from: ' . from . '`ntranslate: ' . Translatetext, 'from auto to English'
;MsgBox Translatetext
TextShowGuiFnc(Translatetext)
}
GoogleTranslateWrapperToEn(Borders := false)
{
ocrReturn := OCR2ToReturn()
Translatetext := GoogleTranslate(ocrReturn, &from := 'auto',"en")
;MsgBox 'from: ' . from . '`ntranslate: ' . Translatetext, 'from auto to English'
;MsgBox Translatetext
TextShowGuiFnc(Translatetext)
}
GoogleTranslate(str, from := 'auto', to := 'en', &variants := '') {
static JS := ObjBindMethod(GetJsObject(), 'eval'), _ := JS(GetJScript())
json := SendRequest(str, Type(from) = 'VarRef' ? %from% : from, to)
return ExtractTranslation(json, from, &variants)
GetJsObject() {
static document := '', JS
if !document {
document := ComObject('HTMLFILE')
document.write('<meta http-equiv="X-UA-Compatible" content="IE=9">')
JS := document.parentWindow
(document.documentMode < 9 && JS.execScript())
}
return JS
}
GetJScript() {
return '
( Join
var TKK="406398.2087938574";function b(r,_){for(var t=0;t<_.length-2;t+=3){var $=_.charAt(t+2),$="a"<=$?$
.charCodeAt(0)-87:Number($),$="+"==_.charAt(t+1)?r>>>$:r<<$;r="+"==_.charAt(t)?r+$&4294967295:r^$}return r}
function tk(r){for(var _=TKK.split("."),t=Number(_[0])||0,$=[],a=0,h=0;h<r.length;h++){var n=r.charCodeAt(h);
128>n?$[a++]=n:(2048>n?$[a++]=n>>6|192:(55296==(64512&n)&&h+1<r.length&&56320==(64512&r.charCodeAt(h+1))?
(n=65536+((1023&n)<<10)+(1023&r.charCodeAt(++h)),$[a++]=n>>18|240,$[a++]=n>>12&63|128):$[a++]=n>>12|224,$
[a++]=n>>6&63|128),$[a++]=63&n|128)}for(a=0,r=t;a<$.length;a++)r+=$[a],r=b(r,"+-a^+6");return r=b(r,
"+-3^+b+-f"),0>(r^=Number(_[1])||0)&&(r=(2147483647&r)+2147483648),(r%=1e6).toString()+"."+(r^t)}
)'
}
SendRequest(str, sl, tl) {
static WR := ''
, headers := Map('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8',
'User-Agent' , 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0')
if !WR {
WR := WebRequest()
WR.Fetch('https://translate.google.com',, headers)
}
url := 'https://translate.googleapis.com/translate_a/single?client=gtx'
. '&sl=' . sl . '&tl=' . tl . '&hl=' . tl
. '&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&otf=0&ssel=0&tsel=0&pc=1&kc=1'
. '&tk=' . JS('tk')(str)
return WR.Fetch(url, 'POST', headers, 'q=' . JS('encodeURIComponent')(str))
}
ExtractTranslation(json, from, &variants) {
jsObj := JS('(' . json . ')')
if !IsObject(jsObj.1) {
Loop jsObj.0.length {
variants .= jsObj.0.%A_Index - 1%.0
}
} else {
mainTrans := jsObj.0.0.0
Loop jsObj.1.length {
variants .= '`n+'
obj := jsObj.1.%A_Index - 1%.1
Loop obj.length {
txt := obj.%A_Index - 1%
variants .= (mainTrans = txt ? '' : '`n' . txt)
}
}
}
if !IsObject(jsObj.1)
mainTrans := variants := Trim(variants, ',+`n ')
else
variants := mainTrans . '`n+`n' . Trim(variants, ',+`n ')
(Type(from) = 'VarRef' && %from% := jsObj.8.3.0)
return mainTrans
}
}
class WebRequest
{
__New() {
this.whr := ComObject('WinHttp.WinHttpRequest.5.1')
}
__Delete() {
this.whr := ''
}
Fetch(url, method := 'GET', HeadersMap := '', body := '', getRawData := false) {
this.whr.Open(method, url, true)
for name, value in HeadersMap
this.whr.SetRequestHeader(name, value)
this.error := ''
this.whr.Send(body)
this.whr.WaitForResponse()
status := this.whr.status
if (status != 200)
this.error := 'HttpRequest error, status: ' . status . ' — ' . this.whr.StatusText
SafeArray := this.whr.responseBody
pData := NumGet(ComObjValue(SafeArray) + 8 + A_PtrSize, 'Ptr')
length := SafeArray.MaxIndex() + 1
if !getRawData
res := StrGet(pData, length, 'UTF-8')
else {
outData := Buffer(length, 0)
DllCall('RtlMoveMemory', 'Ptr', outData, 'Ptr', pData, 'Ptr', length)
res := outData
}
return res
}
}
Simple Gui that I made to view and edit without copying to clipboard:
Code: Select all
;Translatetext := "Transtex"
;TextShowGuiFnc(Translatetext)
TextShowGuiFnc(ParamText)
{
;AutoGUI 2.5.8 creator: Alguimist autohotkey.com/boards/viewtopic.php?f=64&t=89901
;AHKv2converter creator: github.com/mmikeww/AHK-v2-script-converter
;Easy_AutoGUI_for_AHKv2 github.com/samfisherirl/Easy-Auto-GUI-for-AHK-v2
myGui := Gui()
guiHeightStart := 300
guiWidthtStart := 600
myGui.OnEvent("Size", GuiSize)
myGui.Opt("+Resize -MinimizeBox +AlwaysOnTop +OwnDialogs +Owner")
ogcButtonCopy := myGui.Add("Button", "x" guiWidthtStart - 82 " y" guiHeightStart - 25 " w80 h23", "&Copy")
ogcButtonClose := myGui.Add("Button", "x" guiWidthtStart - 166 " y" guiHeightStart - 25 " w80 h23", "&Close")
Edit1 := myGui.Add("Edit", "x0 y-3 w" guiWidthtStart " h" guiHeightStart - 25 " +Multi")
Edit1.SetFont("s12")
ogcButtonCopy.OnEvent("Click", EditCopy)
ogcButtonClose.OnEvent("Click", GuiClose)
Edit1.OnEvent("Change", OnEventHandler)
myGui.OnEvent('Close', (*) => GuiClose())
myGui.Title := "Show Text"
myGui.Show("w" guiWidthtStart " h" guiHeightStart " ")
Edit1.Text := ParamText
GuiSize(thisGui, MinMax, A_GuiWidth, A_GuiHeight)
{ ; V1toV2: Added bracket
If (A_EventInfo == 1) {
Return
}
ogcButtonCopy.Move(A_GuiWidth - 82,A_GuiHeight - 25)
ogcButtonClose.Move(A_GuiWidth - 166,A_GuiHeight - 25)
ogcButtonCopy.Redraw()
ogcButtonClose.Redraw()
Edit1.Move(0,0,A_GuiWidth,A_GuiHeight -25)
Edit1.Redraw()
} ; V1toV2: Added bracket before function
GuiClose(*){
myGui.Destroy()
}
EditCopy(*){
A_Clipboard := Edit1.Text
}
OnEventHandler(*)
{
; ToolTip("Click! This is a sample action.`n"
; . "Active GUI element values include:`n"
; . "ogcButtonCopy => " ogcButtonCopy.Text "`n"
; . "ogcButtonClose => " ogcButtonClose.Text "`n"
; . "Edit1 => " Edit1.Value "`n", 77, 277)
; SetTimer () => ToolTip(), -3000 ; tooltip timer
}
}
Screenshot: I collected the hepzine in a zip file: I haven't dealt with Autohotkey for a long time, this is my first time with V2. Please be aware that things can go wrong.;; #INCLUDE EXTENSION
;{-----------------------------------------------
;
; #Include Snipper - Extension - Acrobat.ahk
; #Include Snipper - Extension - Word.ahk
; #Include Snipper - Extension - Outlook.ahk
#Include Snipper - Extension - TextShowOnGui.ahk
#include Snipper - Extension - OCR.ahk
#include Snipper - Extension - Google Translate.ahk
Re: Snipper - Window Snipping Tool
A tip:
I was having trouble taking a screenshot of some tooltips, so I thought I'd use it in conjunction with the built-in snipping tool. This works.
Press Win+Shift+S to make the built-in snipping tool overlay the screen, then hold down the Windows key and drag the mouse to capture the tooltip without losing it. The only problem is that Snipper's lines don't come out when drawing the screen, but the image is captured successfully. Maybe it can be turned into a plugin.
Translated with www.DeepL.com/Translator (free version)
I was having trouble taking a screenshot of some tooltips, so I thought I'd use it in conjunction with the built-in snipping tool. This works.
Press Win+Shift+S to make the built-in snipping tool overlay the screen, then hold down the Windows key and drag the mouse to capture the tooltip without losing it. The only problem is that Snipper's lines don't come out when drawing the screen, but the image is captured successfully. Maybe it can be turned into a plugin.
Translated with www.DeepL.com/Translator (free version)
Re: Snipper - Window Snipping Tool
Hello everyone,
This tool seems great to me but like these colleagues I also need to be able to draw squares to highlight parts of the captured image with a fixed color and the possibility of blurring other parts to hide confidential information from the capture. I've been looking for how to do it but I've only been making ahk scripts for a month and I'm not able to. Any clue on how to do it? I haven't found any plug-in that does it.
Thank you all!
This tool seems great to me but like these colleagues I also need to be able to draw squares to highlight parts of the captured image with a fixed color and the possibility of blurring other parts to hide confidential information from the capture. I've been looking for how to do it but I've only been making ahk scripts for a month and I'm not able to. Any clue on how to do it? I haven't found any plug-in that does it.
Thank you all!
Re: Snipper - Window Snipping Tool
@Insaid — There are free tools like Greenshot that do what you are seeking.
Re: Snipper - Window Snipping Tool
Thank you for answering so quickly!
I know some of these tools but in my corporate environment I am not allowed to download and run applications but I have managed to get Autohotkey approved, which would be a perfect solution for me.
I know some of these tools but in my corporate environment I am not allowed to download and run applications but I have managed to get Autohotkey approved, which would be a perfect solution for me.
Re: Snipper - Window Snipping Tool
It’s a shame your company would rather have you spend time creating the equivalent of existing tools from scratch for something you and your colleagues need rather than having IT review and revise their policies or at least approve tools necessary for your job.
Re: Snipper - Window Snipping Tool
@boiler
I totally agree with you but I have to look for an alternative. I have worked for many years in the same company and I know that I cannot change it. At least now I have the option of getting an alternative thanks to Autohotkey. I hope that someone with the same needs but more knowledge can make a plug-in that works for us. While I will continue learning to try to do it myself when I have enough knowledge.
I totally agree with you but I have to look for an alternative. I have worked for many years in the same company and I know that I cannot change it. At least now I have the option of getting an alternative thanks to Autohotkey. I hope that someone with the same needs but more knowledge can make a plug-in that works for us. While I will continue learning to try to do it myself when I have enough knowledge.
Re: Snipper - Window Snipping Tool
Actually, it wouldn't be too difficult to manipulate this tool. You can put snips on top of each other and quote them collectively in a new one. You can adjust the transparency with a small plugin. There are also resizing and duplication plugins available.Insaid wrote: ↑03 Jan 2024, 11:59@boiler
I totally agree with you but I have to look for an alternative. I have worked for many years in the same company and I know that I cannot change it. At least now I have the option of getting an alternative thanks to Autohotkey. I hope that someone with the same needs but more knowledge can make a plug-in that works for us. While I will continue learning to try to do it myself when I have enough knowledge.
Another simple plugin can be made for the highlight line at the top.
Re: Snipper - Window Snipping Tool
@hasantr
Thanks for your tips. I will review the existing code well and try to do what I need although I think I have to learn something more. If I get it I will share the code here for whoever may need it. I found this code for the blur: viewtopic.php?f=76&t=119389
Thanks for your tips. I will review the existing code well and try to do what I need although I think I have to learn something more. If I get it I will share the code here for whoever may need it. I found this code for the blur: viewtopic.php?f=76&t=119389
Re: Snipper - Window Snipping Tool
when set Quality in SaveBitmapToFile
it will throw error in this line
Type need put in first
I just put type in the first par,but not work
I dont know which is Number,Target,Offset
it will throw error in this line
Code: Select all
NumPut(Quality, NumGet(NumPut(4, NumPut(1, _p + 0, "UPtr") + 20, "UInt"), "UPtr"), "UInt")
I just put type in the first par,but not work
I dont know which is Number,Target,Offset
Re: Snipper - Window Snipping Tool
@FanaticGuru can be hidden from the Alt+Tab and Win+Tab menu using the Alt+Tab property.
This is how it was in Ahk v1 Version. Is there any reason not to make it default? Would you consider adding it to the settings menu?
Code: Select all
+ToolWindow
This is how it was in Ahk v1 Version. Is there any reason not to make it default? Would you consider adding it to the settings menu?
- FanaticGuru
- Posts: 1945
- Joined: 30 Sep 2013, 22:25
Re: Snipper - Window Snipping Tool
Updated in First Post
Change Log: 2024 01 09
FG
Change Log: 2024 01 09
- Fixed bug in Gdip SaveBitMapToFile when setting image quality
- Added Settings_Image_Quality to DEFAULT SETTING - VARIABLES section to set image quality
- Added Settings_ToolWindow to DEFAULT SETTING - VARIABLES section so Snips can be set to be hidden from the taskbar
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
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
- FanaticGuru
- Posts: 1945
- Joined: 30 Sep 2013, 22:25
Re: Snipper - Window Snipping Tool
hasantr wrote: ↑09 Jan 2024, 04:19@FanaticGurucan be hidden from the Alt+Tab and Win+Tab menu using the Alt+Tab property.Code: Select all
+ToolWindow
This is how it was in Ahk v1 Version. Is there any reason not to make it default? Would you consider adding it to the settings menu?
I like having an icon on the taskbar when I have a Snip created but I added a setting for it. At some point I might expand the Gui Settings dialog to allow it to be changed on the fly.
It would be nice to have all the Settings_ variables adjustable through a dialog. I just find creating Gui tedious. I will probably eventually do it though.
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
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
- FanaticGuru
- Posts: 1945
- Joined: 30 Sep 2013, 22:25
Re: Snipper - Window Snipping Tool
viv wrote: ↑08 Jan 2024, 23:46when set Quality in SaveBitmapToFile
it will throw error in this lineType need put in firstCode: Select all
NumPut(Quality, NumGet(NumPut(4, NumPut(1, _p + 0, "UPtr") + 20, "UInt"), "UPtr"), "UInt")
I just put type in the first par,but not work
I dont know which is Number,Target,Offset
Fixed. This bug seems to be in every conversion of the Gdip library to v2 that I looked at. The confusion is probably because NumPut and NumGet changed from v1 to v2 beta and then again for v2 release.
Kind of sad there is not a rock solid Gdip v2 out there. I have searched and every one I have found has numerous conversion bugs. It is one reason I created the class of select Gdip functions used in Snipper.
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
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