=====Capturing the contents of a window=====
//by Richard Russell, May 2007 (updated)//\\ \\ You can //capture//, as a bitmap file, the contents of your program's main output window using the ***SCREENSAVE** (or ***GSAVE**) command. But what if you want to save not your output window but the contents of a dialogue box, Direct3D window or other window? There is no equivalent built-in command to do that.\\ \\ The procedures listed below will capture to a file the contents of the window whose handle is specified. If one doesn't work the other probably will. The procedures as listed save the image as a BMP file; if you want to use a different file format change **PROCsaveasbmp(hbm%, file$)** to [[/Saving%20a%20GIF%20image|PROCsavegif(hbm%, file$)]] or [[/Saving%20a%20JPEG%20image|PROCsavejpg(hbm%, file$, quality%)]] etc. as appropriate.
===== Method one =====
This method is most appropriate for dialogue boxes and other child windows. It will work even if the window is wholly or partially obscured, but won't work with Direct3D windows:
DEF PROCcapturewindow1(hwnd%, file$)
PRF_CHILDREN = 16
PRF_ERASEBKGND = 8
PRF_CLIENT = 4
PRF_NONCLIENT = 2
WM_PRINT = 791
LOCAL rc{}, hdc%, hbm%, oldbm%
DIM rc{l%,t%,r%,b%}
SYS "GetWindowRect", hwnd%, rc{}
SYS "CreateCompatibleDC", @memhdc% TO hdc%
SYS "CreateCompatibleBitmap", @memhdc%, rc.r%-rc.l%, rc.b%-rc.t% TO hbm%
SYS "SelectObject", hdc%, hbm% TO oldbm%
SYS "SendMessage", hwnd%, WM_PRINT, hdc%, \
\ PRF_CHILDREN+PRF_ERASEBKGND+PRF_CLIENT+PRF_NONCLIENT
SYS "SelectObject", hdc%, oldbm%
PROCsaveasbmp(hbm%, file$)
SYS "DeleteObject", hbm%
SYS "DeleteDC", hdc%
ENDPROC
So if you wanted to capture the contents of a dialogue box you might do:
PROCcapturewindow1(!dlg%, @dir$+"dialogue.bmp")
where **dlg%** is the value returned from **FN_newdialog**.\\ \\ The procedure calls the **PROCsaveasbmp** routine which is listed below. If you want to capture the window as a JPEG or GIF file change the **PROCsaveasbmp** to [[/Saving%20a%20JPEG%20image|PROCsavejpeg]] or [[/Saving%20a%20GIF%20image|PROCsavegif]] respectively.
===== Method two =====
This method is appropriate for Direct3D windows and other windows which don't give the required results with the previous method. However if the window is wholly or partially obscured, the captured image will include the obscuring object:
DEF PROCcapturewindow2(hwnd%, file$)
LOCAL rc{}, hdc%, hbm%, ddc%, oldbm%
DIM rc{l%,t%,r%,b%}
SYS "GetWindowRect", hwnd%, rc{}
SYS "CreateDC", "DISPLAY", 0, 0, 0 TO ddc%
SYS "CreateCompatibleDC", @memhdc% TO hdc%
SYS "CreateCompatibleBitmap", @memhdc%, rc.r%-rc.l%, rc.b%-rc.t% TO hbm%
SYS "SelectObject", hdc%, hbm% TO oldbm%
SYS "BitBlt", hdc%, 0, 0, rc.r%-rc.l%, rc.b%-rc.t%, ddc%, rc.l%, rc.t%, &CC0020
SYS "SelectObject", hdc%, oldbm%
PROCsaveasbmp(hbm%, file$)
SYS "DeleteObject", hbm%
SYS "DeleteDC", hdc%
SYS "DeleteDC", ddc%
ENDPROC
So if you wanted to capture your Direct3D output you might do:
PROCcapturewindow2(@hwnd%, @dir$+"direct3d.bmp")
The procedure calls the **PROCsaveasbmp** routine which is listed below. If you want to capture the window as a JPEG or GIF file change the **PROCsaveasbmp** to [[/Saving%20a%20JPEG%20image|PROCsavejpeg]] or [[/Saving%20a%20GIF%20image|PROCsavegif]] respectively.
===== Method three =====
This is similar to **Method two**, but simulates capturing the mouse pointer in addition to the window contents:
DEF PROCCaptureWindowWithMousePointer(hwnd%, file$)
LOCAL ddc%, hdc%, hbm%, oldbm%, hicon%
LOCAL rc{}, ci{}, ii{}
DIM rc{l%,t%,r%,b%} : REM RECT{}
DIM ci{cbSize%, flags%, hCursor%, ScreenPosX%, ScreenPosY%} : REM CURSORINFO{}
DIM ii{fIcon%, xHotspot%, yHotspot%, hbmMask%, hbmColor%} : REM ICONINFO{}
ci.cbSize% = DIM(ci{})
SRCCOPY = &CC0020
SYS "GetCursorInfo", ci{}
SYS "CopyIcon", ci.hCursor% TO hicon%
SYS "CreateDC", "DISPLAY", 0, 0, 0 TO ddc%
SYS "CreateCompatibleDC", @memhdc% TO hdc%
SYS "GetWindowRect", hwnd%, rc{}
SYS "CreateCompatibleBitmap", @memhdc%, rc.r%-rc.l%, rc.b%-rc.t% TO hbm%
SYS "SelectObject", hdc%, hbm% TO oldbm%
SYS "BitBlt", hdc%, 0, 0, rc.r%-rc.l%, rc.b%-rc.t%, ddc%, rc.l%, rc.t%, SRCCOPY
IF hicon% THEN
ci.ScreenPosX% -= rc.l%
ci.ScreenPosY% -= rc.t%
SYS "GetIconInfo", hicon%, ii{}
ci.ScreenPosX% -= ii.xHotspot%
ci.ScreenPosY% -= ii.yHotspot%
SYS "DrawIcon", hdc%, ci.ScreenPosX%, ci.ScreenPosY%, hicon%
SYS "DeleteObject", ii.hbmMask%
SYS "DeleteObject", ii.hbmColor%
SYS "DestroyIcon", hicon%
ENDIF
SYS "SelectObject", hdc%, oldbm%
PROCsaveasbmp(hbm%, file$)
SYS "DeleteObject", hbm%
SYS "DeleteDC", hdc%
SYS "DeleteDC", ddc%
ENDPROC
// by Michael Hutton, November 2010//\\ \\ Capturing the whole desktop can be done with:
DEF PROC_CaptureScreenWithMousePointer(_file$)
LOCAL ddc%, hdc%, hbm%, oldbm%, xscreen%, yscreen% , hicon% , X%, Y%
LOCAL ci{}, ii{}
DIM ci{ cbSize%, flags%, hCursor%, ScreenPosX%, ScreenPosY%} : REM CURSORINFO{}
DIM ii{ fIcon%, xHotspot%, yHotspot%, hbmMask%, hbmColor%} : REM ICONINFO{}
ci.cbSize% = DIM(ci{})
SYS "GetCursorInfo", ci{}
SYS "CopyIcon", ci.hCursor% TO hicon%
SYS "GetIconInfo", hicon%, ii{}
X% = ci.ScreenPosX% - ii.xHotspot%
Y% = ci.ScreenPosY% - ii.yHotspot%
SYS "GetSystemMetrics", 0 TO xscreen%
SYS "GetSystemMetrics", 1 TO yscreen%
SYS "CreateDC", "DISPLAY", 0, 0, 0 TO ddc%
SYS "CreateCompatibleDC", @memhdc% TO hdc%
SYS "CreateCompatibleBitmap", @memhdc%, xscreen%, yscreen% TO hbm%
SYS "SelectObject", hdc%, hbm% TO oldbm%
SYS "BitBlt", hdc%, 0, 0, xscreen%, yscreen%, ddc%, 0, 0, &CC0020
SYS "DrawIcon", hdc%, X%, Y%, hicon%
SYS "SelectObject", hdc%, oldbm%
PROCsaveasbmp(hbm%, _file$)
SYS "DeleteObject", hbm%
SYS "DeleteDC", hdc%
SYS "DeleteDC", ddc%
SYS "DestroyIcon", hicon%
SYS "DeleteObject", ii.hbmMask%
SYS "DeleteObject", ii.hbmColor%
ENDPROC
===== Saving a bitmap to a file =====
This routine can be used whenever you want to save to file a bitmap whose handle you know:
DEF PROCsaveasbmp(hbm%,file$)
LOCAL bmp%, width%, height%, size%, data%, res%
REM. Find the bitmap dimensions and file size:
DIM bmp% LOCAL 26
bmp% = (bmp% + 3) AND -4
SYS "GetObject", hbm%, 24, bmp% TO res%
IF res%=0 ERROR 100, "GetObject failed"
width% = bmp%!4
height% = bmp%!8
size% = 54 + height%*((width%*3 + 3) AND -4)
REM. Allocate and zero memory for BMP file:
SYS "GlobalAlloc", &40, size% TO data%
IF data%=0 ERROR 100, "GlobalAlloc failed"
REM. Store file and bitmap headers:
data%?0 = ASC"B"
data%?1 = ASC"M"
data%!2 = size%
data%!10 = 54
data%!14 = 40
data%!18 = width%
data%!22 = height%
data%!26 = &180001
REM. Copy the image into the DIB:
SYS "GetDIBits", @memhdc%, hbm%, 0, height%, data%+54, data%+14, 0 TO res%
IF res%<>height% ERROR 100, "GetDIBits failed"
REM. Save the output file:
OSCLI "SAVE """+file$+""" "+STR$~data%+" +"+STR$~size%
SYS "GlobalFree", data%
ENDPROC