WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: mueer01 on August 09, 2021, 07:42:46 AM

Title: SnapShot with specific coordinates
Post by: mueer01 on August 09, 2021, 07:42:46 AM
Hello,

I found  the function SnapShot(request) with a good example.
But is it possible to make a Snapshot from specific coordinates?

i.e. MySnapShot(x1, y1, x2, y2)

Regards,
Erhard
Title: Re: SnapShot with specific coordinates
Post by: td on August 09, 2021, 08:07:46 AM
Never had a reason to perform this task but one approach would be to take the image of the entire desktop and assuming you know the coordinates clip the part you are interested in after performing some coordinate conversion. Maybe consider using WIL CLR hosting with a dotNet assembly to clip the image.

Perhaps other forum members can suggest the best method for clipping the image or a better approach to the problem.
Title: Re: SnapShot with specific coordinates
Post by: JTaylor on August 09, 2021, 08:31:38 AM
The Omnibus extender will do the cropping but it has to be in a file.

Jim
Title: Re: SnapShot with specific coordinates
Post by: td on August 09, 2021, 08:39:24 AM
Or use the dotNet "System.Drawing" assembly:

https://docs.microsoft.com/en-us/dotnet/api/system.drawing.bitmap.clone?view=net-5.0 (https://docs.microsoft.com/en-us/dotnet/api/system.drawing.bitmap.clone?view=net-5.0)

But your extender most likely requires less of a learning curve for those not initiated into the world of dotNet scripting with WinBatch.
Title: Re: SnapShot with specific coordinates
Post by: td on August 10, 2021, 07:58:06 AM
Here is a quick and dirty example of using the "System.Drawing" assembly to create a clipped bitmap of a screenshot.

Code (winbatch) Select
;; Load needed assembly.
ObjectClrOption('useany', 'System.Drawing')

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Example from the help file
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Takes a bitmap snapshot of the screen and pastes it to the clipboard.
Snapshot(0)
;returns the size of buffer needed for a subsequent BinaryAlloc,
;but doesn't attempt to place the contents of clipboard into a buffer
size=BinaryClipGet(0,8)
;allocates a data buffer
bb=BinaryAlloc(size)
;read file format type CF_DIB
BinaryClipGet(bb,8)
; need to add first 14 bytes to make it
; a BMP file format
bmpdatasize=14
bb2=BinaryAlloc(size + bmpdatasize)
;The characters identifying the bitmap.'BM'
BinaryPokeStr(bb2, 0, "BM")
;Complete file size in bytes.
BinaryPoke4(bb2,2,size + bmpdatasize)
;Reserved
BinaryPoke4(bb2,6,0)
;Data offset
headersize=BinaryPeek4(bb,0)
dataoffset = headersize + bmpdatasize
BinaryPoke4(bb2,10,dataoffset)
BinaryCopy(bb2,bmpdatasize,bb,0,size)
; Note:Moved bitmap file name to a variable.
BmpFile = "c:\temp\screenshot.bmp"
BinaryWrite(bb2,BmpFile)
BinaryFree(bb)
BinaryFree(bb2)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Use the System.Drawing.Bitmap class to create
;; a new image of just part of the screen.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

objBmp = ObjectClrNew('System.Drawing.Bitmap', BmpFile)

bmpH = objBmp.Height()
bmpW = objBmp.Width()

; Take a slice out of the middle
nX = bmpW/4
nY = BmpH/4
nW = nX * 2
nH = nY * 2
objRect =  ObjectClrNew('System.Drawing.Rectangle', nX, nY, nW, nH)
nDontCare = 0
nDontCare = ObjectClrType('System.Drawing.Imaging.PixelFormat', nDontCare )

objCrop = objBmp.Clone(objRect, nDontCare)

Clip =  'C:\temp\Clipped.bmp'
objCrop.Save(Clip)

; Clean up.
objCrop.Dispose()
objBmp.Dispose()

Run('mspaint.exe', Clip)


Interesting enough you can use dotNet to get the screen shot but the WIL ScreenShot function does the job without the additional learning curve.
Title: Re: SnapShot with specific coordinates
Post by: stanl on August 10, 2021, 01:06:15 PM
Be nice if you could Sendkey {PRTSC}.....  ;D .
Title: Re: SnapShot with specific coordinates
Post by: ....IFICantBYTE on August 11, 2021, 07:38:24 AM
Search in the tech database... I remember there were dll calls for win32 ways of saving a bmp of the screen via pixel coordinates... getdc .. createcimpatiblebitmap?? Something like that..
Title: Re: SnapShot with specific coordinates
Post by: cssyphus on August 15, 2021, 09:43:41 AM
Jumping in... FWIW, I had to do exactly this today. In the end, I grabbed a small portion of the screen like this (using the freeware gold standard IrfanView with a couple of command-line parameters):


_iviewApp = `C:\Program Files (x86)\IrfanView\i_view32.exe`

run(_iviewApp, `/capture=7=(-360,950,170,22) /title=OBS Rec Status /hide=15`)

timeDelay(5)
winClose(`IrfanView - OBS Rec Status`)


The above grabs a small bit of the screen (170w x 22h - specifically the current Rec/Pause status of OBS Studio) and opens it in an instance of IrfanView sans titlebar, caption, statusbar, menus. Note that it grabs this screenshot from the second monitor, to my left.

The /hide=15 is particularly nice, since that hides every trace of the IrfanView app except the image and window borders. (And, very nicely, IrfanView doesn't remember that setting next time you start it from the start menu - that is, next launch-from-start-menu it will start up as usual, with all that stuff enabled as per normal).

I can then use winPlace() to stick the window wherever I want (again, on mon2) and windowOnTop() to keep it always-visible until I Right-Click to close it from the taskbar (since there's no caption/windowTitle, close X button due to the " /hide=15").

Title: Re: SnapShot with specific coordinates
Post by: td on August 15, 2021, 01:04:36 PM
Here's a rough approximation of a "pure" dotNet approach:

Code (winbatch) Select
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Pure FCL approach.

;; Load needed assembly.
ObjectClrOption('useany', 'System.Drawing')
Clip =  'C:\temp\Clipped.bmp'

; Take a slice from somewhere on the screen.
nX = WinMetrics(0)/4
nY = WinMetrics(1)/4
nW = nX * 2
nH = nY * 2
Format32bppArgb  = ObjectClrType('System.Drawing.Imaging.PixelFormat', 2498570)
objBmp = ObjectClrNew('System.Drawing.Bitmap', nX, nY, Format32bppArgb )

objGraphics = ObjectClrNew('System.Drawing.Graphics')
memGraphic  = objGraphics.FromImage(objBmp)

; Copy a portion of the screen to a bitmap and save it to a file.
Size =  ObjectClrNew('System.Drawing.Size', nW, nH)
memGraphic.CopyFromScreen(nX, nY, 0, 0, Size)

Clip =  'C:\temp\Clipped.bmp'
objBmp.Save(Clip)

; View the result.
Run('mspaint.exe', Clip)


It could be taken a step farther by having the clipped image drawn in a dotNet form window.
Title: Re: SnapShot with specific coordinates
Post by: td on August 16, 2021, 07:56:35 AM
Quote from: cssyphus on August 15, 2021, 09:43:41 AM
Jumping in... FWIW, I had to do exactly this today. In the end, I grabbed a small portion of the screen like this (using the freeware gold standard IrfanView with a couple of command-line parameters):


_iviewApp = `C:\Program Files (x86)\IrfanView\i_view32.exe`

run(_iviewApp, `/capture=7=(-360,950,170,22) /title=OBS Rec Status /hide=15`)

timeDelay(5)
winClose(`IrfanView - OBS Rec Status`)


The above grabs a small bit of the screen (170w x 22h - specifically the current Rec/Pause status of OBS Studio) and opens it in an instance of IrfanView sans titlebar, caption, statusbar, menus. Note that it grabs this screenshot from the second monitor, to my left.

The /hide=15 is particularly nice, since that hides every trace of the IrfanView app except the image and window borders. (And, very nicely, IrfanView doesn't remember that setting next time you start it from the start menu - that is, next launch-from-start-menu it will start up as usual, with all that stuff enabled as per normal).

I can then use winPlace() to stick the window wherever I want (again, on mon2) and windowOnTop() to keep it always-visible until I Right-Click to close it from the taskbar (since there's no caption/windowTitle, close X button due to the " /hide=15").

Looks like an interesting tool.

The OP never mentions what the end-use for the image is so the benefit of displaying the image is unknown. Also, Windows and WinBatch have several built-in methods of displaying a random bitmap in various contexts.

Any of the methods mentioned in this topic including Snapshot can be used in the process of grabbing part of a second, third, or fourth monitor simply by specifying the coordinance.