BigDaddyO Posted April 8, 2020 Share Posted April 8, 2020 This function would be most useful for individuals that use AutoIt to test applications. Typically, I have a log file that contains information on what my tests are doing and any failures. Failures typically get a screenshot and the log gets a link to that screenshot. I've decided that it would be best to store additional detailed information about the error in the screenshot itself by appending an additional section to the screenshot and adding text into that new section. It's also able to put a red box around a specific control. useful if your error is about a specific field value missing or wrong. Below is a fully operational example script with a couple different capture items that are commented out so you can run 1 at a time. Please leave any suggestions for improvements. expandcollapse popup#include <ScreenCapture.au3> #include <WinAPIConv.au3> ;For this test, ensure the AutoIt spy is open so I can grab a control off that If WinExists("(Frozen) AutoIt v3 Window Info", "Basic Control Info") = 0 Then Run("C:\Program Files (x86)\AutoIt3\Au3Info.exe") winwait("(Frozen) AutoIt v3 Window Info", "Basic Control Info", 10) EndIf $sSaveAs = @ScriptDir & "\LogImage.jpg" $sString = "This is my additional log information that i'm attaching to this screenshot" & @CRLF & @CRLF & "It can handle @CRLF!" & @CRLF & @TAB & "But, it Can't handle @Tab" & @CRLF & @CRLF & _ "I've highlighted the control we were looking for in a red box!" $hWindow = WinGetHandle("(Frozen) AutoIt v3 Window Info", "Basic Control Info") $hCtrl = "Edit3" $aWinPos = WinGetPos($hWindow, "") ;~ $sOutput = _ScreenCapture_Log($sSaveAs, $sString) ;Simplest version, capture entire screen, adds 300px wide log to the right ;~ $sOutput = _ScreenCapture_Log($sSaveAs, $sString, $hWindow, $hCtrl, 300, 400) ;Captures entire screen, highlights a control and adds log to the right $sOutput = _ScreenCapture_Log($sSaveAs, $sString, $hWindow, $hCtrl, 300, 400, 2, $aWinPos[0], $aWinPos[1], $aWinPos[2], $aWinPos[3]) ;Capture only the window we are looking for, highlight the control, add log to the right If @error Then MsgBox(0, "FAILURE", "Unable to create screenshot") Else ;Launch the saved screenshot to view results ShellExecute($sOutput) EndIf ; #FUNCTION# ==================================================================================================================== ; Name...........: _ScreenCapture_Log ; Description ...: Captures a screenshot and append a section to include text/log information ; Syntax.........: _ScreenCapture_Log($sSaveAs, $sString) ; Parameters ....: $sFileName - Full path where to save the file. "" to return the GDI image handle ; $sString - The full text to append to the image. Accepts @CRLF but @TAB is not handled ; $hWindow - If you want to highlight a control, you must include the handle to the controls window. Default = "" nothing highlighted ; $hCtrl - If you want to highligh a control, add the controlID or handle. Default = "" nothing highlighted ; $iLogW - How wide do you want the appended string image to be. may be extended automatically depending on position specified. ; $iLogH - How high do you want the appended string image to be. may be extended automatically depending on position specified. ; $iLogPos - Where to place the string image. 0 = Left of capture, 1 = Above Capture, 2 = Right of Capture, 3 = Below Capture. Default = 2 (Right of) ; $iCaptX - If you want to capture specific coordinates instead of the entire screen, enter the x coord here ; $iCaptY - If you want to capture specific coordinates instead of the entire screen, enter the y coord here ; $iCaptW - If you want to capture specific coordinates instead of the entire screen, enter the width here ; $iCaptH - If you want to capture specific coordinates instead of the entire screen, enter the height here ; $cursor - True = capture the mouse cursor, False = dont capture the cursor. Default = False ; Return values .: Success - Returns the full path to the saved image, of Handle depending on options provided ; Failure - sets @error ; Author ........: BigDaddyO ; Modified ......: ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: _ScreenCapture_Log(@ScriptDir & "\LogImage.jpg", "This is my Log information") ; =============================================================================================================================== Func _ScreenCapture_Log($sFileName = "", $sString = "", $hWindow = "", $hCtrl = "", $iLogW = 300, $iLogH = 300, $iLogPos = 2, $iCaptX = 0, $iCaptY = 0, $iCaptW = -1, $iCaptH = -1, $cursor = False) Local $hBitmap, $hImage, $aDim[2], $aLogPos[4], $aCaptPos[4], $hCanvas, $hGfx, $aCanvas[2], $aCtrlPos, $tPoint, $aRect[4] Local $hBrush, $hFormat, $hFamily, $hFont, $tLayout, $aInfo _GDIPlus_Startup() ; Capture screen If $iCaptW > -1 Then $iCaptW += $iCaptX ;doing this as WinGetPos returns Width instead of x2 If $iCaptH > -1 Then $iCaptH += $iCaptY ;doing this as WinGetPos returns Height instead of y2 $hBitmap = _ScreenCapture_Capture("", $iCaptX, $iCaptY, $iCaptW, $iCaptH, $cursor) If @error Then ConsoleWrite('Failed to perform initial capture using _ScreenCapture_Capture("", ' & $iCaptX & ", " & $iCaptY & ", " & $iCaptW & ", " & $iCaptH & ", " & $cursor & ")" & @CRLF) Return SetError(1) EndIf $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) ;Build a new Bitmap and Graphic to hold the Screenshot and Log Info ;~ Local $aLogPos[4], $aCaptPos[4], $aCanvas[2] $aDim = _GDIPlus_ImageGetDimension($hImage) ;Size of our screenshot ;Where do we want the log to be located Switch $iLogPos Case 0 ;Log goes to the left of screenshot ;Identify the new size of the image If $iLogH > $aDim[1] Then $aCanvas[0] = $aDim[0] + $iLogW $aCanvas[1] = $iLogH Else $aCanvas[0] = $aDim[0] + $iLogW $aCanvas[1] = $aDim[1] $iLogH = $aDim[1] EndIf ;Identify the Size and position of the screenshot in the new image $aCaptPos[0] = $iLogW $aCaptPos[1] = 0 $aCaptPos[2] = $aDim[0] $aCaptPos[3] = $aDim[1] ;Identify the Size and position of the Log text in the new image $aLogPos[0] = 5 $aLogPos[1] = 5 $aLogPos[2] = $iLogW - 10 ;Width will be specified log width - 10 for a 5px border on both sides $aLogPos[3] = $iLogH - 10 ;Log Height - 10 for a 5px border on both sides ;Identify the location for the Control Highlight if requested If $hWindow <> "" and $hCtrl <> "" Then $aCtrlPos = ControlGetPos($hWindow, "", $hCtrl) ;Get the location of the control within the window If IsArray($aCtrlPos) Then $tPoint = DllStructCreate("int X;int Y") DllStructSetData($tPoint, "X", $aCtrlPos[0]) DllStructSetData($tPoint, "Y", $aCtrlPos[1]) _WinAPI_ClientToScreen($hWindow, $tPoint) ;Translate the position to the position on screen $aRect[0] = DllStructGetData($tPoint, "X") + $iLogW $aRect[1] = DllStructGetData($tPoint, "Y") $aRect[2] = $aCtrlPos[2] $aRect[3] = $aCtrlPos[3] EndIf EndIf Case 1 ;Log goes Above the screenshot ;Identify the new size of the image If $iLogW > $aDim[0] Then $aCanvas[0] = $iLogW $aCanvas[1] = $aDim[1] + $iLogH Else $aCanvas[0] = $aDim[0] $aCanvas[1] = $aDim[1] + $iLogH $iLogW = $aDim[0] EndIf ;Identify the Size and position of the screenshot in the new image $aCaptPos[0] = 0 $aCaptPos[1] = $iLogH $aCaptPos[2] = $aDim[0] $aCaptPos[3] = $aDim[1] ;Identify the Size and position of the Log text in the new image $aLogPos[0] = 5 $aLogPos[1] = 5 $aLogPos[2] = $aDim[0] - 10 $aLogPos[3] = $iLogH - 10 ;Identify the location for the Control Highlight if requested If $hWindow <> "" and $hCtrl <> "" Then $aCtrlPos = ControlGetPos($hWindow, "", $hCtrl) ;Get the location of the control within the window $tPoint = DllStructCreate("int X;int Y") DllStructSetData($tPoint, "X", $aCtrlPos[0]) DllStructSetData($tPoint, "Y", $aCtrlPos[1]) _WinAPI_ClientToScreen($hWindow, $tPoint) ;Translate the position to the position on screen $aRect[0] = DllStructGetData($tPoint, "X") $aRect[1] = DllStructGetData($tPoint, "Y") + $iLogH $aRect[2] = $aCtrlPos[2] $aRect[3] = $aCtrlPos[3] EndIf Case 2 ;Default, Log goes to the right of the screenshot ;Identify the new size of the image If $iLogH > $aDim[1] Then $aCanvas[0] = $aDim[0] + $iLogW $aCanvas[1] = $iLogH Else $aCanvas[0] = $aDim[0] + $iLogW $aCanvas[1] = $aDim[1] $iLogH = $aDim[1] EndIf ;Identify the Size and position of the screenshot in the new image $aCaptPos[0] = 0 $aCaptPos[1] = 0 $aCaptPos[2] = $aDim[0] $aCaptPos[3] = $aDim[1] ;Identify the Size and position of the Log text in the new image $aLogPos[0] = $aDim[0] + 5 ;Start log text after screenshot width + 5 for border $aLogPos[1] = 5 ;Start log text at the top of the screenshot with a +5 border $aLogPos[2] = $iLogW - 10 ;Width will be specified log width - 10 for a 5px border on both sides $aLogPos[3] = $iLogH - 10 ;Width will be specified log height - 10 for a 5px border on both sides ;Identify the location for the Control Highlight if requested If $hWindow <> "" and $hCtrl <> "" Then $aCtrlPos = ControlGetPos($hWindow, "", $hCtrl) ;Get the location of the control within the window If IsArray($aCtrlPos) Then $tPoint = DllStructCreate("int X;int Y") DllStructSetData($tPoint, "X", $aCtrlPos[0]) DllStructSetData($tPoint, "Y", $aCtrlPos[1]) _WinAPI_ClientToScreen($hWindow, $tPoint) ;Translate the position to the position on screen $aRect[0] = DllStructGetData($tPoint, "X") $aRect[1] = DllStructGetData($tPoint, "Y") $aRect[2] = $aCtrlPos[2] $aRect[3] = $aCtrlPos[3] EndIf EndIf Case 3 ;Log goes below the screenshot ;Identify the new size of the image If $iLogW > $aDim[0] Then $aCanvas[0] = $iLogW $aCanvas[1] = $aDim[1] + $iLogH Else $aCanvas[0] = $aDim[0] $aCanvas[1] = $aDim[1] + $iLogH $iLogW = $aDim[0] EndIf ;Identify the Size and position of the screenshot in the new image $aCaptPos[0] = 0 $aCaptPos[1] = 0 $aCaptPos[2] = $aDim[0] $aCaptPos[3] = $aDim[1] ;Identify the Size and position of the Log text in the new image $aLogPos[0] = 5 $aLogPos[1] = $aDim[1] + 5 $aLogPos[2] = $aDim[0] - 10 $aLogPos[3] = $iLogH - 10 ;Identify the location for the Control Highlight if requested If $hWindow <> "" and $hCtrl <> "" Then $aCtrlPos = ControlGetPos($hWindow, "", $hCtrl) ;Get the location of the control within the window If IsArray($aCtrlPos) Then $tPoint = DllStructCreate("int X;int Y") DllStructSetData($tPoint, "X", $aCtrlPos[0]) DllStructSetData($tPoint, "Y", $aCtrlPos[1]) _WinAPI_ClientToScreen($hWindow, $tPoint) ;Translate the position to the position on screen $aRect[0] = DllStructGetData($tPoint, "X") $aRect[1] = DllStructGetData($tPoint, "Y") $aRect[2] = $aCtrlPos[2] $aRect[3] = $aCtrlPos[3] EndIf EndIf Case Else Return SetError(1) EndSwitch $hCanvas = _GDIPlus_BitmapCreateFromScan0($aCanvas[0], $aCanvas[1]) ;The entire size of the newly widened image $hGfx = _GDIPlus_ImageGetGraphicsContext($hCanvas) _GDIPlus_GraphicsDrawImageRect($hGfx, $hImage, $aCaptPos[0], $aCaptPos[1], $aCaptPos[2], $aCaptPos[3]) ;Draw the captured screen in the proper location for the log ;Draw a frame around the control if that option is selected If $hWindow <> "" and $hCtrl <> "" Then If IsArray($aCtrlPos) Then ;If we are not taking a full screen image, then we need to adjust the position of the red rectangle! $aRect[0] -= $iCaptX $aRect[1] -= $iCaptY $hPen = _GDIPlus_PenCreate(0xFFFF0000, 2) ;Create a red pen _GDIPlus_GraphicsDrawRect($hGfx, $aRect[0], $aRect[1], $aRect[2], $aRect[3], $hPen) ;Draw our rectangle around the control EndIf EndIf ;Now to insert some text into the canvas If $sString <> "" Then $hBrush = _GDIPlus_BrushCreateSolid(0xFFFFFF99) $hFormat = _GDIPlus_StringFormatCreate() $hFamily = _GDIPlus_FontFamilyCreate("Arial") $hFont = _GDIPlus_FontCreate($hFamily, 8, 2) $tLayout = _GDIPlus_RectFCreate($aLogPos[0], $aLogPos[1], $aLogPos[2], $aLogPos[3]) $aInfo = _GDIPlus_GraphicsMeasureString($hGfx, $sString, $hFont, $tLayout, $hFormat) _GDIPlus_GraphicsDrawStringEx($hGfx, $sString, $hFont, $aInfo[0], $hFormat, $hBrush) _GDIPlus_FontDispose($hFont) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_BrushDispose($hBrush) EndIf If $sFileName <> "" Then ;Save the image _GDIPlus_ImageSaveToFile($hCanvas, $sFileName) If @error Then ConsoleWrite("Failed to save the updated canvas" & @CRLF) ;Time for cleanup _GDIPlus_ImageDispose($hCanvas) _WinAPI_DeleteObject($hImage) _GDIPlus_Shutdown() Return SetError(1) Else ConsoleWrite("sucessfully saved the updated canvas" & @CRLF) ;Time for cleanup _GDIPlus_ImageDispose($hCanvas) _WinAPI_DeleteObject($hImage) _GDIPlus_Shutdown() Return $sFileName EndIf Else ;Return the handle to the canvas, can I shutdown GDIPlus now? Return $hCanvas EndIf EndFunc Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now