Jump to content

Get realtime image of a background window (without glitches)


Recommended Posts

the following script does exactly as the topic title describes it, but there's one issue. Occasionally I get black glitches (not full window, but only one segment of a window). The best way to describe it is to try yourself, run the script, then select another window (example: Firefox (main part glitches, the one with the net content, and download window as well) or Winamp (playlist part glitches, the rest is OK)), then press F11, and you'll see what I mean.

the question is: how to resolve the glitches issue and make everything works smooth?

To exit the script, press ESC.

#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <WinApi.au3>

Opt("OnExitFunc", "endscript")
Opt("TrayMenuMode", 1)

HotKeySet("{F11}", "_uzmi_sliku")
HotKeySet("{ESC}", "_izlaz")

Global $window_handle, $window_size, $window_size_x, $window_size_y

Global $window_width = @DesktopWidth/2
Global $window_height = @DesktopHeight/2

Global $Form1 = GUICreate("Press F11 to capture window, press ESC to exit", $window_width, $window_height, -1, -1, $WS_CLIPSIBLINGS, $WS_EX_TOPMOST);+$WS_MINIMIZEBOX+$WS_SIZEBOX, $WS_EX_TOPMOST)
GUISetState(@SW_SHOWNOACTIVATE, $form1)
TrayTip("", "Select another window," & @LF & "for example: Winamp or Firefox" & @LF & "then press F11" & @LF & @LF & "To quit press ESC", 30)
TraySetToolTip("to quit press ESC")

_GDIPlus_Startup()
Global $hGraphic_x = _GDIPlus_GraphicsCreateFromHWND (WinGetHandle($form1))

While 1
    Sleep(10)
WEnd

func _postavi_novu_velicinu()
    $hGraphic_x = _GDIPlus_GraphicsCreateFromHWND (WinGetHandle($form1))
    _GDIPlus_GraphicsClear($hGraphic_x)
EndFunc

func _uzmi_sliku()
    AdlibDisable()
    _postavi_novu_velicinu()
    $window_handle = WinGetHandle("[ACTIVE]")
    $window_size = WinGetPos($window_handle)
    $window_size_x = $window_size[2]/2
    $window_size_y = $window_size[3]/2
    AdlibEnable("myadlib", 50)
EndFunc

func myadlib()
    _ScreenShot_of_a_window($window_handle, $window_size_x, $window_size_y)
EndFunc

func _izlaz()
    AdlibDisable()
    endscript()
    Exit
EndFunc

func endscript()
    _GDIPlus_GraphicsDispose($hGraphic_x)
    _GDIPlus_Shutdown()
EndFunc

func _ScreenShot_of_a_window($i_win_handle, $iW, $iH)
    Local $hDC = _WinAPI_GetWindowDC($i_win_handle)
    Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
    Local $hWinPos = WinGetPos($i_win_handle)
    if @error then Return -1
    Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $hWinPos[2], $hWinPos[3])
    _WinAPI_SelectObject($hMemDC, $hBitmap)
    _PrintWindow($i_win_handle, $hMemDC)
    _WinAPI_DeleteDC($hMemDC)
    _WinAPI_ReleaseDC($i_win_handle, $hDC)
    _SavehBitmapEx($hBitmap, $iW, $iH)
    _WinAPI_DeleteObject($hBitmap)
EndFunc

Func _SavehBitmapEx($hBitmap,$iWidth,$iHeight)
    $bitmap=_GDIPlus_BitmapCreateFromHBITMAP($hbitmap)
    $graphics=_GDIPlus_ImageGetGraphicsContext($bitmap)
    $resizedbitmap=_GDIPlus_BitmapCreateFromGraphics($iWidth,$iHeight,$graphics)
    $graphics2=_GDIPlus_ImageGetGraphicsContext($resizedbitmap)
    _GDIPLUS_GraphicsSetInterpolationMode($graphics2, 2)
    _GDIPlus_GraphicsDrawImageRect($graphics2,$bitmap,0,0,$iWidth,$iHeight)
    _GDIPlus_GraphicsDrawImage ($hGraphic_x, $resizedbitmap, 0, 0)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_GraphicsDispose($graphics2)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_BitmapDispose($resizedbitmap)
EndFunc

Func _GDIPLUS_GraphicsSetInterpolationMode($hGraphics, $iMode)
    DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "hwnd", $hGraphics,"int",$iMode)
EndFunc  ;==>_GDIPLUS_GraphicsSetInterpolationMode

Func _PrintWindow($hWnd, $hMemDC, $iFlag = 0)
    $aRet = DllCall("User32.dll", "int", "PrintWindow", _
                                         "hwnd", $hWnd, _
                                         "hwnd", $hMemDC, _
                                         "int", $iFlag)
    Return $aRet[0]
EndFunc   ;==>_PrintWindow

p.s. I apologize for the complicated example, couldn't make it simpler :P

Edited by sandin
Link to comment
Share on other sites

the following script does exactly as the topic title describes it, but there's one issue. Occasionally I get black glitches (not full window, but only one segment of a window). The best way to describe it is to try yourself, run the script, then select another window (example: Firefox (main part glitches, the one with the net content, and download window as well) or Winamp (playlist part glitches, the rest is OK)), then press F11, and you'll see what I mean.

the question is: how to resolve the glitches issue and make everything works smooth?

To exit the script, press ESC.

#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <WinApi.au3>

Opt("OnExitFunc", "endscript")
Opt("TrayMenuMode", 1)

HotKeySet("{F11}", "_uzmi_sliku")
HotKeySet("{ESC}", "_izlaz")

Global $window_handle, $window_size, $window_size_x, $window_size_y

Global $window_width = @DesktopWidth/2
Global $window_height = @DesktopHeight/2

Global $Form1 = GUICreate("Press F11 to capture window, press ESC to exit", $window_width, $window_height, -1, -1, $WS_CLIPSIBLINGS, $WS_EX_TOPMOST);+$WS_MINIMIZEBOX+$WS_SIZEBOX, $WS_EX_TOPMOST)
GUISetState(@SW_SHOWNOACTIVATE, $form1)
TrayTip("", "Select another window," & @LF & "for example: Winamp or Firefox" & @LF & "then press F11" & @LF & @LF & "To quit press ESC", 30)
TraySetToolTip("to quit press ESC")

_GDIPlus_Startup()
Global $hGraphic_x = _GDIPlus_GraphicsCreateFromHWND (WinGetHandle($form1))

While 1
    Sleep(10)
WEnd

func _postavi_novu_velicinu()
    $hGraphic_x = _GDIPlus_GraphicsCreateFromHWND (WinGetHandle($form1))
    _GDIPlus_GraphicsClear($hGraphic_x)
EndFunc

func _uzmi_sliku()
    AdlibDisable()
    _postavi_novu_velicinu()
    $window_handle = WinGetHandle("[ACTIVE]")
    $window_size = WinGetPos($window_handle)
    $window_size_x = $window_size[2]/2
    $window_size_y = $window_size[3]/2
    AdlibEnable("myadlib", 50)
EndFunc

func myadlib()
    _ScreenShot_of_a_window($window_handle, $window_size_x, $window_size_y)
EndFunc

func _izlaz()
    AdlibDisable()
    endscript()
    Exit
EndFunc

func endscript()
    _GDIPlus_GraphicsDispose($hGraphic_x)
    _GDIPlus_Shutdown()
EndFunc

func _ScreenShot_of_a_window($i_win_handle, $iW, $iH)
    Local $hDC = _WinAPI_GetWindowDC($i_win_handle)
    Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
    Local $hWinPos = WinGetPos($i_win_handle)
    if @error then Return -1
    Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $hWinPos[2], $hWinPos[3])
    _WinAPI_SelectObject($hMemDC, $hBitmap)
    _PrintWindow($i_win_handle, $hMemDC)
    _WinAPI_DeleteDC($hMemDC)
    _WinAPI_ReleaseDC($i_win_handle, $hDC)
    _SavehBitmapEx($hBitmap, $iW, $iH)
    _WinAPI_DeleteObject($hBitmap)
EndFunc

Func _SavehBitmapEx($hBitmap,$iWidth,$iHeight)
    $bitmap=_GDIPlus_BitmapCreateFromHBITMAP($hbitmap)
    $graphics=_GDIPlus_ImageGetGraphicsContext($bitmap)
    $resizedbitmap=_GDIPlus_BitmapCreateFromGraphics($iWidth,$iHeight,$graphics)
    $graphics2=_GDIPlus_ImageGetGraphicsContext($resizedbitmap)
    _GDIPLUS_GraphicsSetInterpolationMode($graphics2, 2)
    _GDIPlus_GraphicsDrawImageRect($graphics2,$bitmap,0,0,$iWidth,$iHeight)
    _GDIPlus_GraphicsDrawImage ($hGraphic_x, $resizedbitmap, 0, 0)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_GraphicsDispose($graphics2)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_BitmapDispose($resizedbitmap)
EndFunc

Func _GDIPLUS_GraphicsSetInterpolationMode($hGraphics, $iMode)
    DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "hwnd", $hGraphics,"int",$iMode)
EndFunc  ;==>_GDIPLUS_GraphicsSetInterpolationMode

Func _PrintWindow($hWnd, $hMemDC, $iFlag = 0)
    $aRet = DllCall("User32.dll", "int", "PrintWindow", _
                                         "hwnd", $hWnd, _
                                         "hwnd", $hMemDC, _
                                         "int", $iFlag)
    Return $aRet[0]
EndFunc   ;==>_PrintWindow

p.s. I apologize for the complicated example, couldn't make it simpler :P

For a better real time image the StretchBlt function from gdi32.dll performs well.

You may be able to modify this example to suit your needs.

The GUI is able to be resized.

;#include <WinAPI.au3>
 #include <GuiConstantsEx.au3>
 #include <WindowsConstants.au3>
 
; http://www.autoitscript.com/forum/index.php?s=&showtopic=87592&view=findpost&p=628901
 Opt("MustDeclareVars", 1)
 
 Global $hGUI2, $Width = 400, $Height = 300, $ZoomFactor = 0.8
 Local $window_handle, $window_size, $window_size_x, $window_size_y, $Disp
 $hGUI2 = GUICreate("Click on Window to capture window, press ESC to exit", $Width, $Height, 80, 400, BitOR($WS_CLIPSIBLINGS, $WS_SIZEBOX), $WS_EX_TOPMOST)
 WinSetTrans("Click on Window to capture window, press ESC to exit", "", 255)
 GUISetState()
 MouseClick("primary", @DesktopWidth, @DesktopDepth / 2, 1);Set active window on startup
 
 Do
     If WinActive($hGUI2) <> 1 Then $window_handle = WinGetHandle("[ACTIVE]")
     $window_size = WinGetPos($window_handle)
     $Disp = WinGetPos($hGUI2)
     $ZoomFactor = $Disp[2] / ($window_size[2] + 10)
     $Width = $Disp[2]
     $Height = $Disp[3]
     $window_size_x = $window_size[2] * $ZoomFactor
     $window_size_y = $window_size[3] * $ZoomFactor
     _MAG($hGUI2, $window_handle)
     Sleep(10)
 Until GUIGetMsg() = $GUI_EVENT_CLOSE
 
; Modified from http://www.autoitscript.com/forum/index.php?s=&showtopic=53471&view=findpost&p=405045
 Func _MAG($MyhWnd, $window_handle)
     Local $MyHDC = DllCall("user32.dll", "int", "GetDC", "hwnd", $MyhWnd); $MyHDC = _WinAPI_GetDC ($MyhWnd)
     If @error Then Return
     Local $DeskHDC = DllCall("user32.dll", "int", "GetDC", "hwnd", $window_handle); $DeskHDC = _WinAPI_GetDC (0)
     If Not @error Then
         DllCall("gdi32.dll", "int", "StretchBlt", "int", $MyHDC[0], "int", 0, "int", 0, "int", $Width, "int", $Height, "int", _
                 $DeskHDC[0], "int", 0, "int", 0, "int", $Width / $ZoomFactor, "int", $Height / $ZoomFactor, "long", $SRCCOPY)
 
         DllCall("user32.dll", "int", "ReleaseDC", "int", $DeskHDC[0], "hwnd", 0); _WinAPI_ReleaseDC ($DeskHDC, 0)
     EndIf
     DllCall("user32.dll", "int", "ReleaseDC", "int", $MyHDC[0], "hwnd", $MyhWnd); _WinAPI_ReleaseDC ($MyhWnd, $MyHDC)
 EndFunc ;==>_MAG
Link to comment
Share on other sites

tnx for reply, that's pretty cool example you gave me :unsure:, but it cannot take picture of a window in the background.

The thing that is making the glitches issue must be user32.dll "PrintWindow" function. If you test this script:

#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <WinApi.au3>

Opt("OnExitFunc", "endscript")
Opt("TrayMenuMode", 1)

HotKeySet("{F11}", "_uzmi_sliku")
HotKeySet("{ESC}", "_izlaz")

Global $window_handle, $window_size, $window_size_x, $window_size_y

Global $window_width = @DesktopWidth/2
Global $window_height = @DesktopHeight/2

Global $Form1 = GUICreate("Press F11 to capture window, press ESC to exit", $window_width, $window_height, -1, -1, $WS_CLIPSIBLINGS, $WS_EX_TOPMOST);+$WS_MINIMIZEBOX+$WS_SIZEBOX, $WS_EX_TOPMOST)
GUISetState(@SW_SHOWNOACTIVATE, $form1)
TrayTip("", "Select another window," & @LF & "for example: Winamp or Firefox" & @LF & "then press F11" & @LF & @LF & "To quit press ESC", 30)
TraySetToolTip("to quit press ESC")

_GDIPlus_Startup()
Global $hGraphic_x = _GDIPlus_GraphicsCreateFromHWND (WinGetHandle($form1))

While 1
    Sleep(10)
WEnd

func _postavi_novu_velicinu()
    $hGraphic_x = _GDIPlus_GraphicsCreateFromHWND (WinGetHandle($form1))
    _GDIPlus_GraphicsClear($hGraphic_x)
EndFunc

func _uzmi_sliku()
    AdlibDisable()
    _postavi_novu_velicinu()
    $window_handle = WinGetHandle("[ACTIVE]")
    $window_size = WinGetPos($window_handle)
    $window_size_x = $window_size[2]/2
    $window_size_y = $window_size[3]/2
    AdlibEnable("myadlib", 50)
EndFunc

func myadlib()
    _ScreenShot_of_a_window($window_handle, $window_size_x, $window_size_y)
EndFunc

func _izlaz()
    AdlibDisable()
    endscript()
    Exit
EndFunc

func endscript()
    _GDIPlus_GraphicsDispose($hGraphic_x)
    _GDIPlus_Shutdown()
EndFunc

func _ScreenShot_of_a_window($i_win_handle, $iW, $iH)
    Local $bitmap5 = _ScreenCapture_CaptureWnd("", WinGetHandle($i_win_handle))
    _SavehBitmapEx($bitmap5, $iW, $iH)
    _WinAPI_DeleteObject($bitmap5)
EndFunc

Func _SavehBitmapEx($hBitmap,$iWidth,$iHeight)
    $bitmap=_GDIPlus_BitmapCreateFromHBITMAP($hbitmap)
    $graphics=_GDIPlus_ImageGetGraphicsContext($bitmap)
    $resizedbitmap=_GDIPlus_BitmapCreateFromGraphics($iWidth,$iHeight,$graphics)
    $graphics2=_GDIPlus_ImageGetGraphicsContext($resizedbitmap)
    _GDIPLUS_GraphicsSetInterpolationMode($graphics2, 2)
    _GDIPlus_GraphicsDrawImageRect($graphics2,$bitmap,0,0,$iWidth,$iHeight)
    _GDIPlus_GraphicsDrawImage ($hGraphic_x, $resizedbitmap, 0, 0)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_GraphicsDispose($graphics2)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_BitmapDispose($resizedbitmap)
EndFunc

Func _GDIPLUS_GraphicsSetInterpolationMode($hGraphics, $iMode)
    DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "hwnd", $hGraphics,"int",$iMode)
EndFunc  ;==>_GDIPLUS_GraphicsSetInterpolationModeoÝ÷ Û*.ßÙe±ç­«mêÞßÛ'¢j+z    bµÈ^²ë"
'!!û§rبƧvz-ºÇ«ßgelªê-¦¸§·§v*º[ºÛa{§vjn­ê',!jÝý²í¢b쨺»®*mb~'¦·¬°]u¶b²Zɧ-÷°whÃlríz{cºËeG­çâ®Ëlr¸©µ«­¢+Ø쥹±Õ±Ðí]¥¹A$¹ÔÌÐì(¥¹±Õ±ÐíÕ¥
½¹ÍѹÑÍà¹ÔÌÐì(¥¹±Õ±Ðí]¥¹½ÝÍ
½¹ÍѹÑ̹ÔÌÐì()!½Ñ-åMÐ ÅÕ½ÐííÄÅôÅÕ½Ðì°ÅÕ½Ðí}ÍÑÉÑ}ÁÑÕÉÅÕ½Ðì¤)!½Ñ-åMÐ ÅÕ½ÐííM
ôÅÕ½Ðì°ÅÕ½Ðí}á¥ÐÅÕ½Ðì¤((ì¡ÑÑÀè¼½ÝÝܹÕѽ¥ÑÍÉ¥Áй½´½½ÉÕ´½¥¹à¹Á¡ÀýÌôµÀíÍ¡½ÝѽÁ¥ôàÜÔäȵÀíÙ¥Üõ¥¹Á½ÍеÀíÀôØÈàäÀÄ)=ÁÐ ÅÕ½Ðí5ÕÍѱÉYÉÌÅÕ½Ðì°Ä¤()±½°ÀÌØí¡U$È°ÀÌØí]¥Ñ ôÐÀÀ°ÀÌØí!¥¡ÐôÌÀÀ°ÀÌØíi½½µÑ½ÈôÀ¸à)1½°ÀÌØíÝ¥¹½Ý}¡¹±°ÀÌØíÝ¥¹½Ý}Í¥é°ÀÌØíÝ¥¹½Ý}Í¥é}à°ÀÌØíÝ¥¹½Ý}Í¥é}ä°ÀÌØí¥ÍÀ(ÀÌØí¡U$ÈôU%
ÉÑ ÅÕ½Ðí
±¥¬½¸]¥¹½ÜѼÁÑÕÉÝ¥¹½Ü°ÁÉÍÌMѼá¥ÐÅÕ½Ðì°ÀÌØí]¥Ñ °ÀÌØí!¥¡Ð°àÀ°ÐÀÀ°   ¥Ñ=H ÀÌØí]M}
1%AM%   1%9L°ÀÌØí]M}M%i    =`¤°ÀÌØí]M}a}Q=A5=MP¤)]¥¹MÑQÉ¹Ì ÅÕ½Ðí
±¥¬½¸]¥¹½ÜѼÁÑÕÉÝ¥¹½Ü°ÁÉÍÌMѼá¥ÐÅÕ½Ðì°ÅÕ½ÐìÅÕ½Ðì°ÈÔÔ¤)U%MÑMÑÑ ¤()]¡¥±Ä(%M±À ÄÀ¤)]¹()Õ¹}ÍÑÉÑ}ÁÑÕÉ ¤($ÀÌØíÝ¥¹½Ý}¡¹±ô]¥¹Ñ!¹± ÅÕ½Ðím
Q%YtÅÕ½Ðì¤(%±¥¹± ÅÕ½Ðíµå±¥ÅÕ½Ðì°ÄÀ¤)¹Õ¹()Õ¹}á¥Ð ¤(%á¥Ð)¹Õ¹()Õ¹µå±¥ ¤(ÀÌØíÝ¥¹½Ý}Í¥éô]¥¹ÑA½Ì ÀÌØíÝ¥¹½Ý}¡¹±¤(ÀÌØí¥ÍÀô]¥¹ÑA½Ì ÀÌØí¡U$Ȥ(ÀÌØíi½½µÑ½ÈôÀÌØí¥ÍÁlÉt¼ ÀÌØíÝ¥¹½Ý}Í¥élÉt¬ÄÀ¤(ÀÌØí]¥Ñ ôÀÌØí¥ÍÁlÉt(ÀÌØí!¥¡ÐôÀÌØí¥ÍÁlÍt(ÀÌØíÝ¥¹½Ý}Í¥é}àôÀÌØíÝ¥¹½Ý}Í¥élÉt¨ÀÌØíi½½µÑ½È(ÀÌØíÝ¥¹½Ý}Í¥é}äôÀÌØíÝ¥¹½Ý}Í¥élÍt¨ÀÌØíi½½µÑ½È(}5 ÀÌØí¡U$È°ÀÌØíÝ¥¹½Ý}¡¹±¤)¹Õ¹((ì5½¥¥É½´¡ÑÑÀè¼½ÝÝܹÕѽ¥ÑÍÉ¥Áй½´½½ÉÕ´½¥¹à¹Á¡ÀýÌôµÀíÍ¡½ÝѽÁ¥ôÔÌÐÜĵÀíÙ¥Üõ¥¹Á½ÍеÀíÀôÐÀÔÀÐÔ)Õ¹}5 ÀÌØí5å¡]¹°ÀÌØíÝ¥¹½Ý}¡¹±¤(1½°ÀÌØí5å!ô±±
±° ÅÕ½ÐíÕÍÈÌȹ±°ÅÕ½Ðì°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÅÕ½ÐíÑÅÕ½Ðì°ÅÕ½Ðí¡Ý¹ÅÕ½Ðì°ÀÌØí5å¡]¹¤ìÀÌØí5å!ô}]¥¹A%}Ñ ÀÌØí5å¡]¹¤(%ÉɽÈQ¡¸IÑÕɸ(1½°ÀÌØíÍ­!ô±±
±° ÅÕ½ÐíÕÍÈÌȹ±°ÅÕ½Ðì°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÅÕ½ÐíÑÅÕ½Ðì°ÅÕ½Ðí¡Ý¹ÅÕ½Ðì°ÀÌØíÝ¥¹½Ý}¡¹±¤ìÀÌØíÍ­!ô}]¥¹A%}Ñ À¤(%9½ÐÉɽÈQ¡¸(±±
±° ÅÕ½Ðí¤Ìȹ±°ÅÕ½Ðì°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÅÕ½ÐíMÑÉÑ¡  ±ÐÅÕ½Ðì°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÀÌØí5å!
lÁt°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°À°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°À°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÀÌØí]¥Ñ °ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÀÌØí!¥¡Ð°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°|(ÀÌØíÍ­!
lÁt°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°À°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°À°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÀÌØí]¥Ñ ¼ÀÌØíi½½µÑ½È°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÀÌØí!¥¡Ð¼ÀÌØíi½½µÑ½È°ÅÕ½Ðí±½¹ÅÕ½Ðì°ÀÌØíMI

=Ad¤((±±
±° ÅÕ½ÐíÕÍÈÌȹ±°ÅÕ½Ðì°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÅÕ½ÐíI±ÍÅÕ½Ðì°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÀÌØíÍ­!
lÁt°ÅÕ½Ðí¡Ý¹ÅÕ½Ðì°À¤ì}]¥¹A%}I±Í ÀÌØíÍ­!°À¤(¹%(±±
±° ÅÕ½ÐíÕÍÈÌȹ±°ÅÕ½Ðì°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÅÕ½ÐíI±ÍÅÕ½Ðì°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÀÌØí5å!
lÁt°ÅÕ½Ðí¡Ý¹ÅÕ½Ðì°ÀÌØí5å¡]¹¤ì}]¥¹A%}I±Í ÀÌØí5å¡]¹°ÀÌØí5å!¤)¹Õ¹ìôôÐí}5

so the problem must lay in the user32.dll's "PrintWindow" function, but is there a solution for this issue? :P

Link to comment
Share on other sites

here's example script to make this issue more understandable:

#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <WinApi.au3>

Opt("OnExitFunc", "endscript")
Opt("TrayMenuMode", 1)

HotKeySet("{F11}", "_uzmi_sliku") ;start
HotKeySet("{ESC}", "_izlaz") ;quit

Global $window_handle, $window_size, $window_size_x = 400, $window_size_y = 300


TrayTip("", "Select another window," & @LF & "for example: Winamp or Firefox" & @LF & "then press F11" & @LF & @LF & "To quit press ESC", 30)
TraySetToolTip("to quit press ESC")

Global $Form2 = GUICreate("_ScreenCapture_CaptureWnd()", 400, 300, 10, 30)
GUISetBkColor(0x00FF00)
WinSetTrans($form2, "", 255)
GUISetState(@SW_SHOWNOACTIVATE, $form2)

;- second window - "PrintWindow" - user32.dll function
Global $Form3 = GUICreate('"PrintWindow" - user32.dll', 400, 300, 10, 130)
GUISetBkColor(0xFF0000)
WinSetTrans($form3, "", 255)
GUISetState(@SW_SHOWNOACTIVATE, $Form3)

;- third window - StretchBlt - gdi32.dll function
Global $Form4 = GUICreate('"StretchBlt" - gdi32.dll', 400, 300, 10, 230)
GUISetBkColor(0x0000FF)
WinSetTrans($form4, "", 255)
GUISetState(@SW_SHOWNOACTIVATE, $Form4)

_GDIPlus_Startup()
Global $hGraphic_1 = _GDIPlus_GraphicsCreateFromHWND (WinGetHandle($form2))
Global $hGraphic_2 = _GDIPlus_GraphicsCreateFromHWND (WinGetHandle($form3))

While 1
    Sleep(10)
WEnd

func _uzmi_sliku()
    AdlibDisable()
    $window_handle = WinGetHandle("[ACTIVE]")
    AdlibEnable("myadlib", 50)
EndFunc

func myadlib()
    _ScreenShot_of_a_window($window_handle, $window_size_x, $window_size_y) ;- first window - _ScreenCapture_CaptureWnd()
    _screenShot_of_a_window2($window_handle, $window_size_x, $window_size_y) ;- second window - "PrintWindow" - user32.dll function
    _screenShot_of_a_window3($window_handle, $window_size_x, $window_size_y) ;- third window - StretchBlt - gdi32.dll function
EndFunc

func _screenShot_of_a_window3($i_win_handle, $iW, $iH)
     _MAG($form4, $i_win_handle, $iW, $iH)
EndFunc

Func _MAG($MyhWnd, $window_handle, $width2, $height2)
    Local $window_size = WinGetPos($window_handle)
    Local $Disp = WinGetPos($MyhWnd)
    Local $Width = $Disp[2]
    Local $Height = $Disp[3]
    Local $zoom_x = $Disp[2]/($window_size[2]+15)
    Local $zoom_y = $Disp[3]/($window_size[3]+15)
    
    Local $MyHDC = DllCall("user32.dll", "int", "GetDC", "hwnd", $MyhWnd); $MyHDC = _WinAPI_GetDC ($MyhWnd)
     If @error Then Return
     Local $DeskHDC = DllCall("user32.dll", "int", "GetDC", "hwnd", $window_handle); $DeskHDC = _WinAPI_GetDC (0)
     If Not @error Then
         DllCall("gdi32.dll", "int", "StretchBlt", "int", $MyHDC[0], "int", 0, "int", 0, "int", $Width, "int", $Height, "int", _
                 $DeskHDC[0], "int", 0, "int", 0, "int", $Width / $zoom_x, "int", $Height / $zoom_y, "long", $SRCCOPY)

         DllCall("user32.dll", "int", "ReleaseDC", "int", $DeskHDC[0], "hwnd", 0); _WinAPI_ReleaseDC ($DeskHDC, 0)
     EndIf
     DllCall("user32.dll", "int", "ReleaseDC", "int", $MyHDC[0], "hwnd", $MyhWnd); _WinAPI_ReleaseDC ($MyhWnd, $MyHDC)
EndFunc ;==>_MAG

func _izlaz()
    AdlibDisable()
    endscript()
    Exit
EndFunc

func endscript()
    _GDIPlus_GraphicsDispose($hGraphic_1)
    _GDIPlus_GraphicsDispose($hGraphic_2)
    _GDIPlus_Shutdown()
EndFunc

func _ScreenShot_of_a_window2($i_win_handle, $iW, $iH)
    Local $hDC = _WinAPI_GetWindowDC($i_win_handle)
    Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
    Local $hWinPos = WinGetPos($i_win_handle)
    if @error then Return -1
    Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $hWinPos[2], $hWinPos[3])
    _WinAPI_SelectObject($hMemDC, $hBitmap)
    _PrintWindow($i_win_handle, $hMemDC)
    _WinAPI_DeleteDC($hMemDC)
    _WinAPI_ReleaseDC($i_win_handle, $hDC)
    _SavehBitmapEx($hBitmap, $iW, $iH, $hGraphic_2)
    _WinAPI_DeleteObject($hBitmap)
EndFunc

func _ScreenShot_of_a_window($i_win_handle, $iW, $iH)
    Local $bitmap5 = _ScreenCapture_CaptureWnd("", WinGetHandle($i_win_handle))
    _SavehBitmapEx($bitmap5, $iW, $iH, $hGraphic_1)
    _WinAPI_DeleteObject($bitmap5)
EndFunc

Func _SavehBitmapEx($hBitmap,$iWidth,$iHeight, $Graphic_handle)
    $bitmap=_GDIPlus_BitmapCreateFromHBITMAP($hbitmap)
    $graphics=_GDIPlus_ImageGetGraphicsContext($bitmap)
    $resizedbitmap=_GDIPlus_BitmapCreateFromGraphics($iWidth,$iHeight,$graphics)
    $graphics2=_GDIPlus_ImageGetGraphicsContext($resizedbitmap)
    _GDIPLUS_GraphicsSetInterpolationMode($graphics2, 2)
    _GDIPlus_GraphicsDrawImageRect($graphics2,$bitmap,0,0,$iWidth,$iHeight)
    _GDIPlus_GraphicsDrawImage ($Graphic_handle, $resizedbitmap, 0, 0)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_GraphicsDispose($graphics2)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_BitmapDispose($resizedbitmap)
EndFunc

Func _GDIPLUS_GraphicsSetInterpolationMode($hGraphics, $iMode)
    DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "hwnd", $hGraphics,"int",$iMode)
EndFunc  ;==>_GDIPLUS_GraphicsSetInterpolationMode

Func _PrintWindow($hWnd, $hMemDC, $iFlag = 0)
    $aRet = DllCall("User32.dll", "int", "PrintWindow", _
                                         "hwnd", $hWnd, _
                                         "hwnd", $hMemDC, _
                                         "int", $iFlag)
    Return $aRet[0]
EndFunc   ;==>_PrintWindow
Link to comment
Share on other sites

@sandin

Occasionally I get black glitches (not full window, but only one segment of a window).

PrintWindow Occasionally Includes Black Rects - VBForums

http://www.vbforums.com/showthread.php?t=555250

Randomly Captured Black Screen By Using PrintWindow API

http://social.msdn.microsoft.com/Forums/en...5-466e5aa91391/

copyFromScreen - no alpha window captured Windows Forms General Windows Forms MSDN Forums.htm

http://social.msdn.microsoft.com/forums/en...b-0d57a5b2e06d/

How to get StdPicture object from PrintWindow API

http://www.codenewsgroups.net/group/micros...topic16871.aspx

Re: PrintWindow API

http://www.tech-archive.net/Archive/Develo...0/msg00087.html

This is as good as it gets for me.

any other problems are due to PrintWindow API limitations,

different window creation methods and video acceleration problems (very glitchy with some video cards).

use pixelchecksum to ignore screen caps of these black windows, so gui is not updated with them.

maybe use pixelchecksum to check for window changes and bypass screen capture

if no change and drop down to slower sample rate with AdlibEnable() to cut high cpu.

Good luck

#include <WindowsConstants.au3>
#include <GDIPlus.au3>

Opt("OnExitFunc", "endscript")
Opt("TrayMenuMode", 1)
Opt('MustDeclareVars', 1)

HotKeySet("{F11}", "_uzmi_sliku")
HotKeySet("{ESC}", "_izlaz")

Global $window_handle, $window_size, $window_size_x, $window_size_y, $iWbuffer, $iHbuffer
Global $window_width = @DesktopWidth / 2
Global $window_height = @DesktopHeight / 2

;speed up script by opening handles to frequently called dlls.
Global $hDLLUser32 = DllOpen("User32.dll")
Global $hDLLGDI32 = DllOpen("GDI32.dll")

Global $fFlag = False, $iPrevhWnd = 0, $iStart = 0
; no need to use WinGetHandle() with GUICreate() (old versions of AutoIt did return an integer instead of real handle)
Global $Form1 = GUICreate("Press F11 to capture window, press ESC to exit", $window_width, $window_height, -1, -1, $WS_CLIPSIBLINGS, $WS_EX_TOPMOST);+$WS_MINIMIZEBOX+$WS_SIZEBOX, $WS_EX_TOPMOST)
GUISetBkColor(0x000000)

_GDIPlus_Startup()
Global $hGraphic_x = _GDIPlus_GraphicsCreateFromHWND($Form1)
GUISetState(@SW_SHOWNOACTIVATE, $Form1)

TrayTip("", "Select another window," & @LF & "for example: Winamp or Firefox" & @LF & "then press F11" & @LF & @LF & "To quit press ESC", 30)
TraySetToolTip("to quit press ESC")

While 1
    Sleep(1000)
WEnd

;after the image is cleared from the gui with GraphicsClear it was repainted to the gui because although AdlibDisable
;is called, the Adlib function wont return until all internal functions are called.
;adding GraphicsClear to the Adlib function with a global boolean flag solves that problem.

;~ Func _postavi_novu_velicinu()
;~  _GDIPlus_GraphicsClear($hGraphic_x)
;~ EndFunc   ;==>_postavi_novu_velicinu

Func _uzmi_sliku()
    AdlibDisable()
;~  _postavi_novu_velicinu()
    $window_handle = WinGetHandle("[ACTIVE]")
    If @error Then Return 0
    
    ;desktop capture very glitchy
    Local $sClass = _WinAPI_GetClassName($window_handle)
    If $sClass == "WorkerW" Or $sClass == "Progman" Then Return 0

    Local $ihWnd = Number($window_handle) ; cast pointer to integer for comparison

    ;clear gui and return if gui form is active window
    If $ihWnd = Number($Form1) Then
        $fFlag = True
        Return 0
    EndIf

    ;if new window, clear gui of previous image (especially required if new window is smaller than previous)
    ;with the previous example script, the background areas not filled by the new window contained the previous window image
    If $ihWnd <> $iPrevhWnd And $iStart Then
        $iPrevhWnd = $ihWnd
        $fFlag = True
    EndIf
    
    If $iStart = 0 Then
        $iPrevhWnd = $ihWnd
        $iStart = 1
    EndIf
    
    ;preset position buffers to prevent clear graphic on first window capture
    $window_size = WinGetPos($window_handle)
    If @error Or Not IsArray($window_size) Then Return 0
    $iWbuffer = $window_size[2]
    $iHbuffer = $window_size[3]

    AdlibEnable("myadlib", 50)
EndFunc   ;==>_uzmi_sliku


Func myadlib()
    $window_size = WinGetPos($window_handle)
    If @error Or Not IsArray($window_size) Then Return 0

    If $window_size[2] <> $iWbuffer Or $window_size[3] <> $iHbuffer Then
        $iWbuffer = $window_size[2]
        $iHbuffer = $window_size[3]
        $fFlag = True ; clear graphic because target window was resized
    EndIf
    $window_size_x = $window_size[2] / 2
    $window_size_y = $window_size[3] / 2
    _ScreenShot_of_a_window($window_handle, $window_size_x, $window_size_y, $window_size[2], $window_size[3])
EndFunc   ;==>myadlib

Func _izlaz()
    AdlibDisable()
    endscript()
    DllClose($hDLLUser32)
    DllClose($hDLLGDI32)
    Exit
EndFunc   ;==>_izlaz

Func endscript()
    _GDIPlus_GraphicsDispose($hGraphic_x)
    _GDIPlus_Shutdown()
EndFunc   ;==>endscript

Func _ScreenShot_of_a_window($i_win_handle, $iW, $iH, $iW2, $iH2)
    Local $aRet = DllCall($hDLLUser32, "hwnd", "GetWindowDC", "hwnd", $i_win_handle)
    If @error Then Return SetError(@error, 0, -1)
    Local $hDC = $aRet[0]
    $aRet = DllCall($hDLLGDI32, "hwnd", "CreateCompatibleDC", "hwnd", $hDC)
    If @error Then Return SetError(@error, 0, -1)
    Local $hMemDC = $aRet[0]
    $aRet = DllCall($hDLLGDI32, "hwnd", "CreateCompatibleBitmap", "hwnd", $hDC, "int", $iW2, "int", $iH2)
    If @error Then Return SetError(@error, 0, -1)
    Local $hBitmap = $aRet[0]
    $aRet = DllCall($hDLLGDI32, "hwnd", "SelectObject", "hwnd", $hMemDC, "hwnd", $hBitmap)
    If @error Then Return SetError(@error, 0, -1)
    Local $hOld = $aRet[0]
    $aRet = DllCall($hDLLUser32, "int", "ReleaseDC", "hwnd", $i_win_handle, "hwnd", $hDC)
    If @error Then Return SetError(@error, 0, -1)
    _PrintWindow($i_win_handle, $hMemDC)
    $aRet = DllCall($hDLLGDI32, "hwnd", "SelectObject", "hwnd", $hMemDC, "hwnd", $hOld)
    If @error Then Return SetError(@error, 0, -1)
    $aRet = DllCall($hDLLGDI32, "int", "DeleteDC", "hwnd", $hMemDC)
    If @error Then Return SetError(@error, 0, -1)
    _SavehBitmapEx($hBitmap, $iW, $iH)
    $aRet = DllCall($hDLLGDI32, "int", "DeleteObject", "int", $hBitmap)
    If @error Then Return SetError(@error, 0, -1)
    
    ;clear gui form and return if AdlibDisable() called
    If $fFlag Then
        _GDIPlus_GraphicsClear($hGraphic_x)
        $fFlag = False
        Return 0
    EndIf
EndFunc   ;==>_ScreenShot_of_a_window

Func _SavehBitmapEx($hBitmap, $iWidth, $iHeight)
    Local $bitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
    Local $graphics = _GDIPlus_ImageGetGraphicsContext($bitmap)
    Local $resizedbitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $graphics)
    Local $graphics2 = _GDIPlus_ImageGetGraphicsContext($resizedbitmap)
    _GDIPLUS_GraphicsSetInterpolationMode($graphics2, 2)
    _GDIPlus_GraphicsDrawImageRect($graphics2, $bitmap, 0, 0, $iWidth, $iHeight)
    _GDIPlus_GraphicsDrawImage($hGraphic_x, $resizedbitmap, 0, 0)
    _GDIPlus_GraphicsDispose($graphics)
    _GDIPlus_GraphicsDispose($graphics2)
    _GDIPlus_BitmapDispose($bitmap)
    _GDIPlus_BitmapDispose($resizedbitmap)
EndFunc   ;==>_SavehBitmapEx

Func _GDIPLUS_GraphicsSetInterpolationMode($hGraphics, $iMode)
    DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "hwnd", $hGraphics, "int", $iMode)
EndFunc   ;==>_GDIPLUS_GraphicsSetInterpolationMode

Func _PrintWindow($hWnd, $hMemDC, $iFlag = 0)
    Local $aRet = DllCall($hDLLUser32, "int", "PrintWindow", _
            "hwnd", $hWnd, _
            "hwnd", $hMemDC, _
            "int", $iFlag)
    Return $aRet[0]
EndFunc   ;==>_PrintWindow

I see fascists...

Link to comment
Share on other sites

@trancexx:

Are you Vista user? If you are, microsoft probably fixed this issue on their newer user32.dll and fixed "PrintWindow" function. If not Vista user, try running Firefox for example, and browse to Google, then try running the posted, exampled script.

@rover:

that is great example, tnx, number of glitches is reduced, but still get black parts occasionally. I tried to do the remake of this using _WinAPI_BitBlt (), but nothing happened, wasn't any different from previous post.

edit: actually, I still get the same amount of glitches :P

Edited by sandin
Link to comment
Share on other sites

Not sure how to invalidate a layout without .NET ..

Like this

DllCall("user32.dll", "int", "InvalidateRect", "hwnd", $hWnd, "ptr", 0, "int", 1)

where $hwnd is the handle of the window to be redrawn,

"ptr",0 is to redraw the whole of the client area, use the address of a rect structure to redraw just the rect,

"int",1 is to redraw the background as well, use 0 to leave the background as is.

See here

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...