CaptureScreen funktioniert nicht

  • Hi Community,

    ich habe das Script CaptureScreen sowie die verbesserte Funktion _ScreenCapture_CaptureWndV2 ausprobiert. Vor einiger Zeit hat es auch kurz funktioniert, später dann garnicht mehr.
    Problem: Nicht das Spiel wird gecaptured sondern die Desktop Oberfläche mit den Koordinaten des Spiels (wenn die Auflösung z.B. sehr niedrig ist, wird auch nur der Teil vom Dekstop genommen).

    Eigentlich sollte die Funktion alles was von der Grafikkarte "gemalt" wird capturen.

    Funktion:

    [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _ScreenCapture_CaptureWndV2
    ; Description ...: Captures a screen shot of a specified window. This function is an alternative to '_ScreenCapture_CaptureWnd'.
    ; It is able to take screenshots of layered windows (drawn by the graphic card). See 'remarks' below.
    ; Syntax.........: _ScreenCapture_CaptureWndV2($sFileName, $hWnd[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]])
    ; Parameters ....: $sFileName - Full path and extension of the image file
    ; $hWnd - Handle to the window to be captured
    ; $iLeft - X coordinate of the upper left corner of the client rectangle
    ; $iTop - Y coordinate of the upper left corner of the client rectangle
    ; $iRight - X coordinate of the lower right corner of the rectangle
    ; $iBottom - Y coordinate of the lower right corner of the rectangle
    ; $fCursor - If True the cursor will be captured with the image
    ; Return values .: See remarks
    ; Remarks .......: 1/ If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
    ; function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
    ; finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle. All coordinates are in
    ; client coordinate mode.
    ;
    ; 2.1/ Layered windows do not appear on screenshots taken by '_ScreenCapture_Capture' because it uses the desktop's
    ; handle whereas the layered windows are drawn directly by the graphic card. 2.2/ '_ScreenCapture_CaptureWnd'
    ; is a wrapper of '_ScreenCapture_Capture' and, therefore, has the same limitations. 2.3/ Instead,
    ; '_ScreenCapture_CaptureWndV2', THIS FUNCTION, is using the handle of the targetted window to perfom its task
    ; (in a similar way than '_ScreenCapture_Capture'uses the Desktop's handle).
    ;
    ; Author ........: Patryk Szczepankiewicz (pszczepa at gmail dot com)
    ; History .......: JAN 21, 2009 - Created
    ; OCT 18, 2010 - First release on the AutoIT forum
    ; OCT 28, 2010 - Cleaned the border code and fixed the capture of the cursor.
    ; APR 06, 2011 - Updated for AutoIT 3.3.6.1
    ; Related .......: _WinAPI_DeleteObject
    ; Link ..........; http://www.autoitscript.com/forum/index.php?showtopic=65008
    ; Example .......; No
    ; Credits .......: Based on Paul Campbell's '_ScreenCapture_Capture' function and inspired by Jennico's '_WinGetBorderSize'.
    ; ===============================================================================================================================
    Func _ScreenCapture_CaptureWndV2($sFileName, $hWnd, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)

    [/autoit][autoit][/autoit][autoit]

    Local $tRect
    Local $iWndX, $iWndY, $iWndW, $iWndH

    [/autoit][autoit][/autoit][autoit]

    Local $tClient
    Local $iBorderV, $iBorderT
    Local $iPicHeight, $iPicWidth
    Local $iPicCursorX, $iPicCursorY

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Local $hDDC, $hCDC, $hBMP, $aCursor, $aIcon, $hIcon

    [/autoit][autoit][/autoit][autoit]

    ; Get the absolute coordinates of the window
    $tRect = _WinAPI_GetWindowRect($hWnd)

    [/autoit][autoit][/autoit][autoit]

    ; Get useful variables
    $iWndX = DllStructGetData($tRect, "Left")
    $iWndY = DllStructGetData($tRect, "Top")
    $iWndW = DllStructGetData($tRect, "Right")
    $iWndH = DllStructGetData($tRect, "Bottom")

    [/autoit][autoit][/autoit][autoit]

    ; Assign automatic values: the right and bottom are computed as
    ; the width and height of the absolute coordinates of the window.
    If $iRight = -1 Then $iRight = $iWndW - $iWndX
    If $iBottom = -1 Then $iBottom = $iWndH - $iWndY

    [/autoit][autoit][/autoit][autoit]

    ; Check user values: check that caller is not putting the top-left
    ; corner out of the window.
    If $iLeft > $iWndW Then $iLeft = $iWndX
    If $iTop > $iWndH Then $iTop = $iWndY

    [/autoit][autoit][/autoit][autoit]

    ; Check user values: check that caller is not asking for a
    ; screenshot bigger than the window itelf.
    If $iRight > $iWndW Then $iRight = $iWndW
    If $iBottom > $iWndH Then $iBottom = $iWndH

    [/autoit][autoit][/autoit][autoit]

    ; Compute the size of the final picture.
    $iPicWidth = $iRight - $iLeft
    $iPicHeight = $iBottom - $iTop

    [/autoit][autoit][/autoit][autoit]

    ; Compute the borders sizes
    $tClient = _WinAPI_GetClientRect($hWnd)
    $iBorderV = (($iWndW - $iWndX) - DllStructGetData($tClient, "Right")) / 2
    $iBorderT = ($iWndH - $iWndY) - DllStructGetData($tClient, "Bottom") - $iBorderV

    [/autoit][autoit][/autoit][autoit]

    ; Transfert color data
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iPicWidth, $iPicHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)
    _WinAPI_BitBlt($hCDC, 0, 0, $iPicWidth, $iPicHeight, $hDDC, $iLeft-$iBorderV, $iTop-$iBorderT, $SRCCOPY)

    [/autoit][autoit][/autoit][autoit]

    ; Add the cursor on the screenshot
    If $fCursor Then
    $aCursor = _WinAPI_GetCursorInfo()
    If $aCursor[1] Then
    $hIcon = _WinAPI_CopyIcon($aCursor[2])
    $aIcon = _WinAPI_GetIconInfo($hIcon)
    $iPicCursorX = $aCursor[3] - $aIcon[2] - $iWndX - $iLeft
    $iPicCursorY = $aCursor[4] - $aIcon[3] - $iWndY - $iTop
    _WinAPI_DrawIcon($hCDC, $iPicCursorX, $iPicCursorY, $hIcon)
    EndIf
    EndIf

    [/autoit][autoit][/autoit][autoit]

    ; Clean and save data
    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
    If $sFileName = "" Then Return $hBMP
    _ScreenCapture_SaveImage($sFileName, $hBMP)

    [/autoit][autoit][/autoit][autoit]

    EndFunc

    [/autoit]

    Jemand eine Idee wie es funktionieren könnte?


    Danke und MfG
    Flo

  • Beachtet man deine Aussage, dass du ein Spiel screenshotten willst, sollte man dich auf die Forenregelnhinweisen. Ungeachtet dessen ist die Funktion schon ziemlich richtig - die Stelle, an der du Sie aufrufst (Viel Besser: Dein ganzer Code - hier hat's niemand nötig deinen Code zu klauen ;) ) interessiert uns viel mehr.

    LG

  • Hi,

    ich verstehe nicht wieso das gegen die Forenregeln verstößt? Das screenshoten von einem Spiel, während man z.B. auf dem Desktop ist, ist definitiv nicht verboten ;)

    [autoit]

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $Button1
    Exit
    Case $Button2
    _getScreen(@ScriptDir & "\Screens\aktuellerscreen.jpg")
    Sleep(5000)
    EndSwitch

    WEnd

    [/autoit][autoit][/autoit][autoit]

    Func _getScreen($dir)
    If WinExists("Starcraft II") Then
    $hWnd = WinGetHandle("Starcraft II")
    _ScreenCapture_SetJPGQuality(50)
    _ScreenCapture_CaptureWndV2($dir,$hWnd)
    endif
    EndFunc

    [/autoit]

    Was meinst du mit es spielt ne Rolle wo ich es aufrufe?

  • Hallo flo,

    poste doch bitte dein komplettes lauffähiges Skript (Syntax) oder finde dich damit ab, dass es Programme gibt die etwas gegen das Fotografieren haben,

    Edit: nachdem ich eine GUI und alle nötigen Includes eingefügt habe läuft es bei mir mit normalen Programmen korrekt:

    Spoiler anzeigen
    [autoit]

    #include <APIConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GUIConstants.au3>
    #Include <WinAPI.au3>
    #Include <ScreenCapture.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $sPicPath = @ScriptDir & "\screens"
    If not FileExists($sPicPath) Then DirCreate($sPicPath)

    [/autoit] [autoit][/autoit] [autoit]

    #region - GUI Create
    GUICreate('')
    $Button2 = GUICtrlCreateButton("&Foto", 10, 10)
    $Button1 = GUICtrlCreateButton("&Schliessen", 10, 50)
    GUISetState()
    #endregion - GUI Create

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $Button1
    Exit
    Case $Button2
    _getScreen($sPicPath & "\aktuellerscreen.jpg")
    ShellExecute($sPicPath & "\aktuellerscreen.jpg")
    Sleep(5000)
    EndSwitch

    [/autoit] [autoit][/autoit] [autoit]

    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _getScreen($sFileName)
    If WinExists("Neue Antwort") Then
    $hWnd = WinGetHandle("Neue Antwort")
    WinActivate($hWnd)
    _ScreenCapture_SetJPGQuality(50)
    _ScreenCapture_CaptureWndV2($sFileName, $hWnd)
    EndIf
    EndFunc ;==>_getScreen

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _ScreenCapture_CaptureWndV2
    ; Description ...: Captures a screen shot of a specified window. This function is an alternative to '_ScreenCapture_CaptureWnd'.
    ; It is able to take screenshots of layered windows (drawn by the graphic card). See 'remarks' below.
    ; Syntax.........: _ScreenCapture_CaptureWndV2($sFileName, $hWnd[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True]]]]])
    ; Parameters ....: $sFileName - Full path and extension of the image file
    ; $hWnd - Handle to the window to be captured
    ; $iLeft - X coordinate of the upper left corner of the client rectangle
    ; $iTop - Y coordinate of the upper left corner of the client rectangle
    ; $iRight - X coordinate of the lower right corner of the rectangle
    ; $iBottom - Y coordinate of the lower right corner of the rectangle
    ; $fCursor - If True the cursor will be captured with the image
    ; Return values .: See remarks
    ; Remarks .......: 1/ If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
    ; function will capture the screen and return a HBITMAP handle to the bitmap image. In this case, after you are
    ; finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle. All coordinates are in
    ; client coordinate mode.
    ;
    ; 2.1/ Layered windows do not appear on screenshots taken by '_ScreenCapture_Capture' because it uses the desktop's
    ; handle whereas the layered windows are drawn directly by the graphic card. 2.2/ '_ScreenCapture_CaptureWnd'
    ; is a wrapper of '_ScreenCapture_Capture' and, therefore, has the same limitations. 2.3/ Instead,
    ; '_ScreenCapture_CaptureWndV2', THIS FUNCTION, is using the handle of the targetted window to perfom its task
    ; (in a similar way than '_ScreenCapture_Capture'uses the Desktop's handle).
    ;
    ; Author ........: Patryk Szczepankiewicz (pszczepa at gmail dot com)
    ; History .......: JAN 21, 2009 - Created
    ; OCT 18, 2010 - First release on the AutoIT forum
    ; OCT 28, 2010 - Cleaned the border code and fixed the capture of the cursor.
    ; APR 06, 2011 - Updated for AutoIT 3.3.6.1
    ; Related .......: _WinAPI_DeleteObject
    ; Link ..........; http://www.autoitscript.com/forum/index.php?showtopic=65008
    ; Example .......; No
    ; Credits .......: Based on Paul Campbell's '_ScreenCapture_Capture' function and inspired by Jennico's '_WinGetBorderSize'.
    ; ===============================================================================================================================
    Func _ScreenCapture_CaptureWndV2($sFileName, $hWnd, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True)
    ConsoleWrite($sFileName & @CRLF)
    Local $tRect
    Local $iWndX, $iWndY, $iWndW, $iWndH

    [/autoit] [autoit][/autoit] [autoit]

    Local $tClient
    Local $iBorderV, $iBorderT
    Local $iPicHeight, $iPicWidth
    Local $iPicCursorX, $iPicCursorY

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Local $hDDC, $hCDC, $hBMP, $aCursor, $aIcon, $hIcon

    [/autoit] [autoit][/autoit] [autoit]

    ; Get the absolute coordinates of the window
    $tRect = _WinAPI_GetWindowRect($hWnd)

    [/autoit] [autoit][/autoit] [autoit]

    ; Get useful variables
    $iWndX = DllStructGetData($tRect, "Left")
    $iWndY = DllStructGetData($tRect, "Top")
    $iWndW = DllStructGetData($tRect, "Right")
    $iWndH = DllStructGetData($tRect, "Bottom")

    [/autoit] [autoit][/autoit] [autoit]

    ; Assign automatic values: the right and bottom are computed as
    ; the width and height of the absolute coordinates of the window.
    If $iRight = -1 Then $iRight = $iWndW - $iWndX
    If $iBottom = -1 Then $iBottom = $iWndH - $iWndY

    [/autoit] [autoit][/autoit] [autoit]

    ; Check user values: check that caller is not putting the top-left
    ; corner out of the window.
    If $iLeft > $iWndW Then $iLeft = $iWndX
    If $iTop > $iWndH Then $iTop = $iWndY

    [/autoit] [autoit][/autoit] [autoit]

    ; Check user values: check that caller is not asking for a
    ; screenshot bigger than the window itelf.
    If $iRight > $iWndW Then $iRight = $iWndW
    If $iBottom > $iWndH Then $iBottom = $iWndH

    [/autoit] [autoit][/autoit] [autoit]

    ; Compute the size of the final picture.
    $iPicWidth = $iRight - $iLeft
    $iPicHeight = $iBottom - $iTop

    [/autoit] [autoit][/autoit] [autoit]

    ; Compute the borders sizes
    $tClient = _WinAPI_GetClientRect($hWnd)
    $iBorderV = (($iWndW - $iWndX) - DllStructGetData($tClient, "Right")) / 2
    $iBorderT = ($iWndH - $iWndY) - DllStructGetData($tClient, "Bottom") - $iBorderV

    [/autoit] [autoit][/autoit] [autoit]

    ; Transfert color data
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iPicWidth, $iPicHeight)
    _WinAPI_SelectObject($hCDC, $hBMP)
    _WinAPI_BitBlt($hCDC, 0, 0, $iPicWidth, $iPicHeight, $hDDC, $iLeft - $iBorderV, $iTop - $iBorderT, $SRCCOPY)

    [/autoit] [autoit][/autoit] [autoit]

    ; Add the cursor on the screenshot
    If $fCursor Then
    $aCursor = _WinAPI_GetCursorInfo()
    If $aCursor[1] Then
    $hIcon = _WinAPI_CopyIcon($aCursor[2])
    $aIcon = _WinAPI_GetIconInfo($hIcon)
    $iPicCursorX = $aCursor[3] - $aIcon[2] - $iWndX - $iLeft
    $iPicCursorY = $aCursor[4] - $aIcon[3] - $iWndY - $iTop
    _WinAPI_DrawIcon($hCDC, $iPicCursorX, $iPicCursorY, $hIcon)
    EndIf
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ; Clean and save data
    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
    If $sFileName = "" Then Return $hBMP
    _ScreenCapture_SaveImage($sFileName, $hBMP)

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>_ScreenCapture_CaptureWndV2

    [/autoit]

    siehe autoit.de/wcf/attachment/13219/

    mfg autoBert

  • Servus,

    bin mir grad nicht sicher, aber in der Beschreibung der Funktion steht doch drin,
    dass es eigentlich nicht geht ;)

    2.1/ Layered windows do not appear on screenshots taken by '_ScreenCapture_Capture' because it uses the desktop's ; handle whereas the layered windows are drawn directly by the graphic card

    Du könntest einfach probieren das Spiel im Fenstermodus zu starten, das könnte dann klappen.

    PS: Wozu willst du das Spiel Screenshotten mit einem Script.
    Die Vermutung ist halt -> Bot, deshalb auch durch die Forenrichtlinien verboten.

    Gruß

    Prajoss

    "Never touch a running System!"

  • Hi,
    einerseits kann es an dem Layered Attribut liegen und andererseits wird Starcraft 2 sicherlich nicht auf die GUI zeichnen, wie GDI+, sondern direkt über die Grafikkarte die Bilddaten ausgeben. Das heißt das Windows, in diesem Fall, gar nichts von den Daten mitbekommt und es daher nur die Möglichkeit gibt das mit Treibern zu hook'en.

  • autoBert

    Das ist mein Skript, ausser das die GUI fehlt.
    Den Desktop zu Screenshotten ist auch kein problem es geht mir hier um 3D-Spiele.

    Prajoss

    Das bezieht sich auf die "alte" Funktion, gerade desshalb gibt es ja diese neue überarbeitete bzw. speziell für Spiele usw. Funktion
    Dieses Tool ist einfach nur zum rumspielen, es ist auch nicht speziell für SC2 sondern auch für viele andere. Später möchte ich gleichzeitig von mehreren Spielen Screenshots haben.

    Sprenger120

    Wie meinst du das genau? Die Funktion soll doch gerade auf die Grafikkarte zugreifen...bzw. auf die Bilddaten die über die Grafikkarte wandern.

    UEZ

    Danke, werde ich ausprobieren =) Ich editiers rein.

    Edit:// Weder 3D-Spiele, noch Textdateien, Ordner uvm. werden geshottet, er macht immer einen Screen von dem aktuellen Fenster. [Win 7, 64 Bit]

    Einmal editiert, zuletzt von Flo (7. Mai 2011 um 20:10)

  • Zitat

    Wie meinst du das genau? Die Funktion soll doch gerade auf die Grafikkarte zugreifen...bzw. auf die Bilddaten die über die Grafikkarte wandern.


    Die Funktion kopiert den Inhalt des Fensters, aber das funktioniert eben nicht bei allen Fenstern ;).

  • Ah okay, danke. Aber wie erklärt sich das, dass es anfangs geklappt hat? Liegt es eventuell an der Grafikkarte selbst, bzw. dem Treiber? Vielleicht ja auch am RAM?

    Danke
    Flo