Jump to content
memerim

Screenshot area of background screen

Recommended Posts

#include <GDIPlus.au3>
#include <WinAPISysWin.au3>


_GDIPlus_Startup()
Global $handle = WinGetHandle("Firefox")
Global $hBitmap = Capture_Window($handle, _WinAPI_GetWindowWidth($handle), _WinAPI_GetWindowHeight($handle))
_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\test.jpg")
_GDIPlus_Shutdown()

;ShellExecute(@ScriptDir & "\test.jpg")


Func Capture_Window($hWnd, $w, $h)
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
    If Int($w) < 1 Then Return SetError(2, 0, 0)
    If Int($h) < 1 Then Return SetError(3, 0, 0)
    Local Const $hDC_Capture = _WinAPI_GetDC(HWnd($hWnd))
    Local Const $hMemDC = _WinAPI_CreateCompatibleDC($hDC_Capture)
    Local Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC_Capture, $w, $h)
    Local Const $hObjectOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    DllCall("gdi32.dll", "int", "SetStretchBltMode", "hwnd", $hDC_Capture, "uint", 4)
    DllCall("user32.dll", "int", "PrintWindow", "hwnd", $hWnd, "handle", $hMemDC, "int", 0)

    _WinAPI_DeleteDC($hMemDC)
    _WinAPI_SelectObject($hMemDC, $hObjectOld)
    _WinAPI_ReleaseDC($hWnd, $hDC_Capture)

    Local Const $hFullScreen = WinGetHandle("[TITLE:Program Manager;CLASS:Progman]")
    Local Const $aFullScreen = WinGetPos($hFullScreen)
    Local Const $c1 = $aFullScreen[2] - @DesktopWidth, $c2 = $aFullScreen[3] - @DesktopHeight
    Local Const $wc1 = $w - $c1, $hc2 = $h - $c2

    If (($wc1 > 1 And $wc1 < $w) Or ($w - @DesktopWidth > 1) Or ($hc2 > 7 And $hc2 < $h) Or ($h - @DesktopHeight > 1)) And (BitAND(WinGetState(HWnd($hWnd)), 32) = 32) Then
        Local $hBmp_t = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
        $hBmp = _GDIPlus_BitmapCloneArea($hBmp_t, 8, 8, $w - 16, $h - 16)
        _GDIPlus_BitmapDispose($hBmp_t)
    Else
        $hBmp = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
    EndIf
    _WinAPI_DeleteObject($hHBitmap)
    Return $hBmp
EndFunc   ;==>Capture_Window

I'm using this script from @UEZ to Screenshots capture background windows

Is possible capture just a area of the handle instead whole screen?

Edited by memerim

Share this post


Link to post
Share on other sites
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <WinAPIHObj.au3>


    Local $handle = WinGetHandle("Sem título - Paint")
    Local $hClone, $hImage, $iX, $i

    ; Initialize GDI+ library
    _GDIPlus_Startup()

    Local $hBitmap = Capture_Window($handle, _WinAPI_GetWindowWidth($handle), _WinAPI_GetWindowHeight($handle))
    ;ConsoleWrite(_WinAPI_GetWindowWidth($handle))

    _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\test.bmp")


    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    ; Create 24 bit bitmap clone
    $iX = _GDIPlus_ImageGetWidth($hImage)
    $iY = _GDIPlus_ImageGetHeight($hImage)
    $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $GDIP_PXF24RGB)
    _GDIPlus_ImageSaveToFile($hClone, @ScriptDir & "\GDIPlus_Image.bmp")

    ; Clean up resources
    _GDIPlus_ImageDispose($hClone)
    _GDIPlus_ImageDispose($hImage)
    _WinAPI_DeleteObject($hBitmap)

    ; Shut down GDI+ library
    _GDIPlus_Shutdown()



Func Capture_Window($hWnd, $w, $h)
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
    If Int($w) < 1 Then Return SetError(2, 0, 0)
    If Int($h) < 1 Then Return SetError(3, 0, 0)
    Local Const $hDC_Capture = _WinAPI_GetDC(HWnd($hWnd))
    Local Const $hMemDC = _WinAPI_CreateCompatibleDC($hDC_Capture)
    Local Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC_Capture, $w, $h)
    Local Const $hObjectOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    DllCall("gdi32.dll", "int", "SetStretchBltMode", "hwnd", $hDC_Capture, "uint", 4)
    DllCall("user32.dll", "int", "PrintWindow", "hwnd", $hWnd, "handle", $hMemDC, "int", 0)

    _WinAPI_DeleteDC($hMemDC)
    _WinAPI_SelectObject($hMemDC, $hObjectOld)
    _WinAPI_ReleaseDC($hWnd, $hDC_Capture)

    Local Const $hFullScreen = WinGetHandle("[TITLE:Program Manager;CLASS:Progman]")
    Local Const $aFullScreen = WinGetPos($hFullScreen)
    Local Const $c1 = $aFullScreen[2] - @DesktopWidth, $c2 = $aFullScreen[3] - @DesktopHeight
    Local Const $wc1 = $w - $c1, $hc2 = $h - $c2

    If (($wc1 > 1 And $wc1 < $w) Or ($w - @DesktopWidth > 1) Or ($hc2 > 7 And $hc2 < $h) Or ($h - @DesktopHeight > 1)) And (BitAND(WinGetState(HWnd($hWnd)), 32) = 32) Then
        Local $hBmp_t = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
        $hBmp = _GDIPlus_BitmapCloneArea($hBmp_t, 8, 8, $w - 16, $h - 16)
        _GDIPlus_BitmapDispose($hBmp_t)
    Else
        $hBmp = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
    EndIf
    _WinAPI_DeleteObject($hHBitmap)
    Return $hBmp
EndFunc   ;==>Capture_Window

The script fromy @UEZ  saves the bmp in 32bits, i've been trying convert it to 24bits to use with my bmp search script, as it looks for 24bits bmps.

Using script above from help file:

https://www.autoitscript.com/autoit3/docs/libfunctions/_GDIPlus_BitmapCloneArea.htm

But it never saves the cloned 24bits bitmap

Edited by memerim

Share this post


Link to post
Share on other sites
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <WinAPIHObj.au3>

Local $handle = WinGetHandle("[CLASS:SciTEWindow]", "")
Local $hClone, $hImage, $iX, $i

; Initialize GDI+ library
_GDIPlus_Startup()

Local $hBitmap = Capture_Window($handle, _WinAPI_GetWindowWidth($handle), _WinAPI_GetWindowHeight($handle))
;ConsoleWrite(_WinAPI_GetWindowWidth($handle))

_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\test.bmp")

; Create 24 bit bitmap clone
$iX = _GDIPlus_ImageGetWidth($hBitmap)
$iY = _GDIPlus_ImageGetHeight($hBitmap)
$hClone = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $iX, $iY, $GDIP_PXF24RGB)
_GDIPlus_ImageSaveToFile($hClone, @ScriptDir & "\GDIPlus_Image.bmp")

; Clean up resources
_GDIPlus_ImageDispose($hClone)
_WinAPI_DeleteObject($hBitmap)

; Shut down GDI+ library
_GDIPlus_Shutdown()



Func Capture_Window($hWnd, $w, $h)
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
    If Int($w) < 1 Then Return SetError(2, 0, 0)
    If Int($h) < 1 Then Return SetError(3, 0, 0)
    Local Const $hDC_Capture = _WinAPI_GetDC(HWnd($hWnd))
    Local Const $hMemDC = _WinAPI_CreateCompatibleDC($hDC_Capture)
    Local Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC_Capture, $w, $h)
    Local Const $hObjectOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    DllCall("gdi32.dll", "int", "SetStretchBltMode", "hwnd", $hDC_Capture, "uint", 4)
    DllCall("user32.dll", "int", "PrintWindow", "hwnd", $hWnd, "handle", $hMemDC, "int", 0)

    _WinAPI_DeleteDC($hMemDC)
    _WinAPI_SelectObject($hMemDC, $hObjectOld)
    _WinAPI_ReleaseDC($hWnd, $hDC_Capture)

    Local Const $hFullScreen = WinGetHandle("[TITLE:Program Manager;CLASS:Progman]")
    Local Const $aFullScreen = WinGetPos($hFullScreen)
    Local Const $c1 = $aFullScreen[2] - @DesktopWidth, $c2 = $aFullScreen[3] - @DesktopHeight
    Local Const $wc1 = $w - $c1, $hc2 = $h - $c2

    If (($wc1 > 1 And $wc1 < $w) Or ($w - @DesktopWidth > 1) Or ($hc2 > 7 And $hc2 < $h) Or ($h - @DesktopHeight > 1)) And (BitAND(WinGetState(HWnd($hWnd)), 32) = 32) Then
        Local $hBmp_t = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
        $hBmp = _GDIPlus_BitmapCloneArea($hBmp_t, 8, 8, $w - 16, $h - 16)
        _GDIPlus_BitmapDispose($hBmp_t)
    Else
        $hBmp = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
    EndIf
    _WinAPI_DeleteObject($hHBitmap)
    Return $hBmp
EndFunc   ;==>Capture_Window

 

Share this post


Link to post
Share on other sites

Thank you Kafu, know if its possible capture just a area instead whole handle screen?

 

-EDIT- Im using this function in a loop, and after some time pop a msg saying  something like "out of memory", i saw in help many gdi clean up functions, should i use _gdi plus start up in the beggining of each loop and gdi shut down in the end of the loop?

Edited by memerim

Share this post


Link to post
Share on other sites

I think _WinAPI_DeleteObject($hBitmap) did not delete the object resulting in a memory leak, try this with _GDIPlus_ImageDispose($hBitmap) in your loop.

#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <WinAPIHObj.au3>

Local $handle = WinGetHandle("[CLASS:SciTEWindow]", "")

Local $iRegion_X = 10, $iRegion_Y = 10, $iRegion_W = 100, $iRegion_H = 100

; Initialize GDI+ library
_GDIPlus_Startup()

Local $hBitmap = Capture_Window($handle, _WinAPI_GetWindowWidth($handle), _WinAPI_GetWindowHeight($handle))


_GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & "\test.bmp")

; Create 24 bit bitmap clone

Local $hClone = _GDIPlus_BitmapCloneArea($hBitmap, $iRegion_X, $iRegion_Y, $iRegion_W, $iRegion_H, $GDIP_PXF24RGB)
_GDIPlus_ImageSaveToFile($hClone, @ScriptDir & "\GDIPlus_Image.bmp")

; Clean up resources
_GDIPlus_ImageDispose($hClone)
_GDIPlus_ImageDispose($hBitmap)

; Shut down GDI+ library
_GDIPlus_Shutdown()


Func Capture_Window($hWnd, $w, $h)
    If Not IsHWnd($hWnd) Then Return SetError(1, 0, 0)
    If Int($w) < 1 Then Return SetError(2, 0, 0)
    If Int($h) < 1 Then Return SetError(3, 0, 0)
    Local Const $hDC_Capture = _WinAPI_GetDC(HWnd($hWnd))
    Local Const $hMemDC = _WinAPI_CreateCompatibleDC($hDC_Capture)
    Local Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC_Capture, $w, $h)
    Local Const $hObjectOld = _WinAPI_SelectObject($hMemDC, $hHBitmap)
    DllCall("gdi32.dll", "int", "SetStretchBltMode", "hwnd", $hDC_Capture, "uint", 4)
    DllCall("user32.dll", "int", "PrintWindow", "hwnd", $hWnd, "handle", $hMemDC, "int", 0)

    _WinAPI_DeleteDC($hMemDC)
    _WinAPI_SelectObject($hMemDC, $hObjectOld)
    _WinAPI_ReleaseDC($hWnd, $hDC_Capture)

    Local Const $hFullScreen = WinGetHandle("[TITLE:Program Manager;CLASS:Progman]")
    Local Const $aFullScreen = WinGetPos($hFullScreen)
    Local Const $c1 = $aFullScreen[2] - @DesktopWidth, $c2 = $aFullScreen[3] - @DesktopHeight
    Local Const $wc1 = $w - $c1, $hc2 = $h - $c2

    If (($wc1 > 1 And $wc1 < $w) Or ($w - @DesktopWidth > 1) Or ($hc2 > 7 And $hc2 < $h) Or ($h - @DesktopHeight > 1)) And (BitAND(WinGetState(HWnd($hWnd)), 32) = 32) Then
        Local $hBmp_t = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
        $hBmp = _GDIPlus_BitmapCloneArea($hBmp_t, 8, 8, $w - 16, $h - 16)
        _GDIPlus_BitmapDispose($hBmp_t)
    Else
        $hBmp = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
    EndIf
    _WinAPI_DeleteObject($hHBitmap)
    Return $hBmp
EndFunc   ;==>Capture_Window

 

Edited by KaFu

Share this post


Link to post
Share on other sites

Thank you again Kafu, but instead cropping a area of the clone bmp, is possible the Capture_Window function save the screenshot of a custom area?

Im asking because im looping this function, and its generating a 4mb file in each second, its 14gb of 'useless' data  per hour just to find a bmp.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...