Ticket #1991: ScreenCaptureV2.2.au3

File ScreenCaptureV2.2.au3, 9.9 KB (added by Chess, 12 years ago)

Update for _ScreenCapture_CaptureV2 _ScreenCapture_CaptureWndV2 Added optional parameter $iBitBltFlag - Flag to pass to the _WinAPI_BitBlt operation default it BitOR($SRCCOPY, $CAPTUREBLT) instead of $SRCCOPY only Tested with AutoIT 3.3.6.1 Fix over previous version with gross error where $SRCCPY was used instead of $iBitBltFlag

Line 
1#include-once
2#include "StdLib\WindowsConstants.au3" ; << MAKES A LOT OF SCREENCAPTURE.AU3 CONSTANTS USELESS (eg. $SM_CXSCREEN, $SRCCOPY, $CAPTUREBLT)
3#include "StdLib\WinAPI.au3"
4#include "StdLib\ScreenCapture.au3"
5
6;Opt("MustDeclareVars", 1)
7
8Global Const $__SCREENCAPTURECONSTANT_DEFAULT_BITBLT_FLAG = BitOR($SRCCOPY, $CAPTUREBLT)
9
10
11; #FUNCTION# ====================================================================================================================
12; Name...........: _ScreenCapture_CaptureV2
13; Description ...: Captures a region of the screen
14; Syntax.........: _ScreenCapture_Capture([$sFileName = ""[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True[, $iBitBltFlag = Default]]]]]]])
15; Parameters ....: $sFileName   - Full path and extension of the image file
16;                  $iLeft       - X coordinate of the upper left corner of the rectangle
17;                  $iTop        - Y coordinate of the upper left corner of the rectangle
18;                  $iRight      - X coordinate of the lower right corner of the rectangle.  If this is  -1,  the  current  screen
19;                  +width will be used.
20;                  $iBottom     - Y coordinate of the lower right corner of the rectangle.  If this is  -1,  the  current  screen
21;                  +height will be used.
22;                  $fCursor     - If True the cursor will be captured with the image
23;                  $iBitBltFlag - Flag to pass to the _WinAPI_BitBlt operation (default it BitOR($SRCCOPY, $CAPTUREBLT))
24; Return values .: See remarks
25; Author ........: Paul Campbell (PaulIA)
26; History .......: OCT 25, 2011 - Added $iBitBltFlag parameter. It uses $CAPTUREBLT by default in order to capture layered windows
27; Remarks .......: If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
28;                  function will capture the screen and return a HBITMAP handle to the bitmap image.  In this case, after you are
29;                  finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle.
30;+
31;                  Requires GDI+: GDI+ requires a redistributable for applications  that
32;                  run on the Microsoft Windows NT 4.0 SP6, Windows 2000, Windows 98, and Windows Me operating systems.
33; Related .......: _WinAPI_DeleteObject, _ScreenCapture_SaveImage
34; Link ..........:
35; Example .......: Yes
36; ===============================================================================================================================
37Func _ScreenCapture_CaptureV2($sFileName = "", $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True, $iBitBltFlag = Default)
38        If $iRight = -1 Then $iRight = _WinAPI_GetSystemMetrics($SM_CXSCREEN)
39        If $iBottom = -1 Then $iBottom = _WinAPI_GetSystemMetrics($SM_CYSCREEN)
40        If $iRight < $iLeft Then Return SetError(-1, 0, 0)
41        If $iBottom < $iTop Then Return SetError(-2, 0, 0)
42        If $iBitBltFlag = Default Then $iBitBltFlag = $__SCREENCAPTURECONSTANT_DEFAULT_BITBLT_FLAG
43
44        Local $iW = ($iRight - $iLeft) + 1
45        Local $iH = ($iBottom - $iTop) + 1
46        Local $hWnd = _WinAPI_GetDesktopWindow()
47        Local $hDDC = _WinAPI_GetDC($hWnd)
48        Local $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
49        Local $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iW, $iH)
50        _WinAPI_SelectObject($hCDC, $hBMP)
51        _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, $iLeft, $iTop, $iBitBltFlag)
52
53        If $fCursor Then
54                Local $aCursor = _WinAPI_GetCursorInfo()
55                If $aCursor[1] Then
56                        Local $hIcon = _WinAPI_CopyIcon($aCursor[2])
57                        Local $aIcon = _WinAPI_GetIconInfo($hIcon)
58                        _WinAPI_DeleteObject($aIcon[4]) ; delete bitmap mask return by _WinAPI_GetIconInfo()
59                        _WinAPI_DrawIcon($hCDC, $aCursor[3] - $aIcon[2] - $iLeft, $aCursor[4] - $aIcon[3] - $iTop, $hIcon)
60                        _WinAPI_DestroyIcon($hIcon)
61                EndIf
62        EndIf
63
64        _WinAPI_ReleaseDC($hWnd, $hDDC)
65        _WinAPI_DeleteDC($hCDC)
66        If $sFileName = "" Then Return $hBMP
67
68        _ScreenCapture_SaveImage($sFileName, $hBMP)
69        _WinAPI_DeleteObject($hBMP)
70EndFunc   ;==>_ScreenCapture_CaptureV2
71
72; #FUNCTION# ====================================================================================================================
73; Name...........: _ScreenCapture_CaptureWndV2
74; Description ...: Captures a screen shot of a specified window. This function is an alternative to '_ScreenCapture_CaptureWnd'.
75;                  It is able to take screenshots of layered windows (drawn by the graphic card). See 'remarks' below.
76; Syntax.........: _ScreenCapture_CaptureWndV2($sFileName, $hWnd[, $iLeft = 0[, $iTop = 0[, $iRight = -1[, $iBottom = -1[, $fCursor = True[, $iBitBltFlag = Default]]]]]])
77; Parameters ....: $sFileName   - Full path and extension of the image file
78;                  $hWnd        - Handle to the window to be captured
79;                  $iLeft       - X coordinate of the upper left corner of the client rectangle
80;                  $iTop        - Y coordinate of the upper left corner of the client rectangle
81;                  $iRight      - X coordinate of the lower right corner of the rectangle
82;                  $iBottom     - Y coordinate of the lower right corner of the rectangle
83;                  $fCursor     - If True the cursor will be captured with the image
84;                  $iBitBltFlag - Flag to pass to the _WinAPI_BitBlt operation (default it BitOR($SRCCOPY, $CAPTUREBLT))
85; Return values .: See remarks
86; Remarks .......: 1/ If FileName is not blank this function will capture the screen and save it to file. If FileName is blank, this
87;                  function will capture the screen and return a HBITMAP handle to the bitmap image.  In this case, after you are
88;                  finished with the bitmap you must call _WinAPI_DeleteObject to delete the bitmap handle.  All coordinates are  in
89;                  client coordinate mode.
90;
91;                  2.1/ Layered windows do not appear on screenshots taken by '_ScreenCapture_Capture' because it uses the desktop's
92;                  handle whereas the layered windows are drawn directly by the graphic card. 2.2/ '_ScreenCapture_CaptureWnd'
93;                  is a wrapper of '_ScreenCapture_Capture' and, therefore, has the same limitations. 2.3/ Instead,
94;                  '_ScreenCapture_CaptureWndV2', THIS FUNCTION, is using the handle of the targetted window to perfom its task
95;                  (in a similar way than '_ScreenCapture_Capture'uses the Desktop's handle).
96;
97; Author ........: Patryk Szczepankiewicz (pszczepa at gmail dot com)
98; History .......: JAN 21, 2009 - Created
99;                  OCT 18, 2010 - First release on the AutoIT forum
100;                  OCT 28, 2010 - Cleaned the border code and fixed the capture of the cursor.
101;                  APR 06, 2011 - Updated for AutoIT 3.3.6.1
102;                  OCT 25, 2011 - Added $iBitBltFlag parameter. It uses $CAPTUREBLT by default in order to capture layered windows
103; Related .......: _WinAPI_DeleteObject
104; Link ..........; http://www.autoitscript.com/forum/index.php?showtopic=65008
105; Example .......; No
106; Credits .......: Based on Paul Campbell's '_ScreenCapture_Capture' function and inspired by Jennico's '_WinGetBorderSize'.
107; ===============================================================================================================================
108Func _ScreenCapture_CaptureWndV2($sFileName, $hWnd, $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $fCursor = True, $iBitBltFlag = Default)
109
110        Local $tRect
111        Local $iWndX, $iWndY, $iWndW, $iWndH
112
113        Local $tClient
114        Local $iBorderV, $iBorderT
115        Local $iPicHeight, $iPicWidth
116        Local $iPicCursorX, $iPicCursorY
117
118
119        Local $hDDC, $hCDC, $hBMP, $aCursor, $aIcon, $hIcon
120
121        ; Default parameters
122        If $iBitBltFlag = Default Then $iBitBltFlag = $__SCREENCAPTURECONSTANT_DEFAULT_BITBLT_FLAG
123
124        ; Get the absolute coordinates of the window
125        $tRect = _WinAPI_GetWindowRect($hWnd)
126
127        ; Get useful variables
128        $iWndX = DllStructGetData($tRect, "Left")
129        $iWndY = DllStructGetData($tRect, "Top")
130        $iWndW = DllStructGetData($tRect, "Right")
131        $iWndH = DllStructGetData($tRect, "Bottom")
132
133        ; Assign automatic values: the right and bottom are computed as
134        ; the width and height of the absolute coordinates of the window.
135        If $iRight = -1 Then $iRight = $iWndW - $iWndX
136        If $iBottom = -1 Then $iBottom = $iWndH - $iWndY
137
138        ; Check user values: check that caller is not putting the top-left
139        ; corner out of the window.
140        If $iLeft > $iWndW Then $iLeft = $iWndX
141        If $iTop > $iWndH Then $iTop = $iWndY
142
143        ; Check user values: check that caller is not asking for a
144        ; screenshot bigger than the window itelf.
145        If $iRight > $iWndW Then $iRight = $iWndW
146        If $iBottom > $iWndH Then $iBottom = $iWndH
147
148        ; Compute the size of the final picture.
149        $iPicWidth = $iRight - $iLeft
150        $iPicHeight = $iBottom - $iTop
151
152        ; Compute the borders sizes
153        $tClient = _WinAPI_GetClientRect($hWnd)
154        $iBorderV = (($iWndW - $iWndX) - DllStructGetData($tClient, "Right")) / 2
155        $iBorderT = ($iWndH - $iWndY) - DllStructGetData($tClient, "Bottom") - $iBorderV
156
157        ; Transfert color data
158        $hDDC = _WinAPI_GetDC($hWnd)
159        $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
160        $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iPicWidth, $iPicHeight)
161        _WinAPI_SelectObject($hCDC, $hBMP)
162        _WinAPI_BitBlt($hCDC, 0, 0, $iPicWidth, $iPicHeight, $hDDC, $iLeft - $iBorderV, $iTop - $iBorderT, $iBitBltFlag)
163
164        ; Add the cursor on the screenshot
165        If $fCursor Then
166                $aCursor = _WinAPI_GetCursorInfo()
167                If $aCursor[1] Then
168                        $hIcon = _WinAPI_CopyIcon($aCursor[2])
169                        $aIcon = _WinAPI_GetIconInfo($hIcon)
170                        $iPicCursorX = $aCursor[3] - $aIcon[2] - $iWndX - $iLeft
171                        $iPicCursorY = $aCursor[4] - $aIcon[3] - $iWndY - $iTop
172                        _WinAPI_DrawIcon($hCDC, $iPicCursorX, $iPicCursorY, $hIcon)
173                EndIf
174        EndIf
175
176        ; Clean and save data
177        _WinAPI_ReleaseDC($hWnd, $hDDC)
178        _WinAPI_DeleteDC($hCDC)
179        If $sFileName = "" Then Return $hBMP
180        _ScreenCapture_SaveImage($sFileName, $hBMP)
181
182EndFunc   ;==>_ScreenCapture_CaptureWndV2