I have the following code, which uses F2 to capture active window. In other words, if we are in any window, and we press the F2, will capture the window in the clipboard, and we can paste it to Paint, for example.
Note that i also use the WinGetPosEX in order to avoid the WinGetPos few pixels offset error of Win10 Aero etc....
The problem is the following:
If I capture the active window when part of it is off the desktop, this part is NOT captured.
For example i get the following:
How can i solve this, please?
Code: Select all
F2::
Clipboard := ; Clear the clipboard.
; create a Temp Folder
FileRemoveDir, %A_ScriptDir%\Temp_ScreenShot_Files, 1
sleep 200
FileCreateDir, %A_ScriptDir%\Temp_ScreenShot_Files
; get the active window handle for the WinGetPosEx call
WinGet,Handle1,ID,A
; get the offsets
WinGetPosEx(Handle1,rxx,ryy,rww,rhh)
; get the selected Window area image to clipboard:
DllCall( "DeleteObject", UInt,hBM )
hBM := ""
hBM := GDI_CaptureScreen( rxx, ryy, rww, rhh )
GDI_SaveBitmap( hBM, A_ScriptDir . "\Temp_ScreenShot_Files\Temp_Screenshot.bmp" )
ImageToClipboard( A_ScriptDir . "\Temp_ScreenShot_Files\Temp_Screenshot.bmp")
; delete the Temp Folder
FileRemoveDir, %A_ScriptDir%\Temp_ScreenShot_Files, 1
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ImageToClipboard(Filename)
{
hbm := DllCall("LoadImage","uint",0,"str",Filename,"uint",0,"int",0,"int",0,"uint",0x10)
if !hbm
return
DllCall("OpenClipboard","uint",0)
DllCall("EmptyClipboard")
; Place the data on the clipboard. CF_BITMAP=0x2
if !DllCall("SetClipboardData","uint",0x2,"uint",hbm)
DllCall("DeleteObject","uint",hbm)
DllCall("CloseClipboard")
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen( X, Y, W, H, ByRef Checksum="" ) {
tDC := DllCall( "CreateCompatibleDC", UInt,0 )
hBM := DllCall( "CopyImage", UInt,DllCall( "CreateBitmap", Int,W, Int,H, UInt,1, UInt,24
, UInt,0 ), UInt,0, Int,0, Int,0, UInt,0x2008, UInt )
oBM := DllCall( "SelectObject", UInt,tDC, UInt,hBM ), hDC := DllCall( "GetDC", UInt,0 )
DllCall( "BitBlt"
, UInt,tDC, UInt,0, UInt,0, Int,W, Int,H, UInt,hDC, UInt,X, UInt,Y, UInt,0x00CC0020 )
DllCall( "ReleaseDC", UInt,0, UInt,hDC ), DllCall( "SelectObject", UInt,tDC, UInt,oBM )
If ( Checksum <> "" )
VarSetCapacity( BM,24,0 ), DllCall( "GetObject", UInt,hBM, UInt,24, UInt,&BM )
, DllCall( "shlwapi\HashData", UInt,NumGet(BM,20), UInt,NumGet( BM,12 )*NumGet( BM,8 )
, Int64P,Checksum, UInt,7 )
Return hBM, DllCall( "DeleteDC", UInt,tDC )
}
GDI_SaveBitmap( hBM, File ) {
DllCall( "GetObject", Int,hBM, Int,VarSetCapacity($,84), UInt,NumPut(0,$,40,"Short")-42 )
Numput( VarSetCapacity(BFH,14,0)+40, Numput((NumGet($,44)+54),Numput(0x4D42,BFH)-2)+4 )
If ( hF := DllCall( "CreateFile", Str,File,UInt,2**30,UInt,2,Int,0,UInt,2,Int64,0 ) ) > 0
DllCall( "WriteFile", UInt,hF, UInt,&BFH, UInt,14, IntP,0,Int,0 ) ; BITMAPFILEHEADER
, DllCall( "WriteFile", UInt,hF, UInt,&$+24, UInt,40, IntP,0,Int,0 ) ; BITMAPINFOHEADER
, DllCall( "WriteFile", UInt,hF, UInt,NumGet($,20), UInt,NumGet($,44), UIntP,BW, Int,0 )
, DllCall( "CloseHandle", UInt,hF )
Return BW ? 54+BW : 0
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WinGetPosEx(hWindow,ByRef X="",ByRef Y="",ByRef Width="",ByRef Height="",ByRef Offset_X="",ByRef Offset_Y="")
{
Static Dummy5693
,RECTPlus
,S_OK:=0x0
,DWMWA_EXTENDED_FRAME_BOUNDS:=9
;-- Workaround for AutoHotkey Basic
PtrType:=(A_PtrSize=8) ? "Ptr":"UInt"
;-- Get the window's dimensions
; Note: Only the first 16 bytes of the RECTPlus structure are used by the
; DwmGetWindowAttribute and GetWindowRect functions.
VarSetCapacity(RECTPlus,24,0)
DWMRC:=DllCall("dwmapi\DwmGetWindowAttribute"
,PtrType,hWindow ;-- hwnd
,"UInt",DWMWA_EXTENDED_FRAME_BOUNDS ;-- dwAttribute
,PtrType,&RECTPlus ;-- pvAttribute
,"UInt",16) ;-- cbAttribute
if (DWMRC<>S_OK)
{
if ErrorLevel in -3,-4 ;-- Dll or function not found (older than Vista)
{
;-- Do nothing else (for now)
}
else
outputdebug,
(ltrim join`s
Function: %A_ThisFunc% -
Unknown error calling "dwmapi\DwmGetWindowAttribute".
RC=%DWMRC%,
ErrorLevel=%ErrorLevel%,
A_LastError=%A_LastError%.
"GetWindowRect" used instead.
)
;-- Collect the position and size from "GetWindowRect"
DllCall("GetWindowRect",PtrType,hWindow,PtrType,&RECTPlus)
}
;-- Populate the output variables
X:=Left :=NumGet(RECTPlus,0,"Int")
Y:=Top :=NumGet(RECTPlus,4,"Int")
Right :=NumGet(RECTPlus,8,"Int")
Bottom :=NumGet(RECTPlus,12,"Int")
Width :=Right-Left
Height :=Bottom-Top
OffSet_X:=0
OffSet_Y:=0
;-- If DWM is not used (older than Vista or DWM not enabled), we're done
if (DWMRC<>S_OK)
Return &RECTPlus
;-- Collect dimensions via GetWindowRect
VarSetCapacity(RECT,16,0)
DllCall("GetWindowRect",PtrType,hWindow,PtrType,&RECT)
GWR_Width :=NumGet(RECT,8,"Int")-NumGet(RECT,0,"Int")
;-- Right minus Left
GWR_Height:=NumGet(RECT,12,"Int")-NumGet(RECT,4,"Int")
;-- Bottom minus Top
;-- Calculate offsets and update output variables
NumPut(Offset_X:=(Width-GWR_Width)//2,RECTPlus,16,"Int")
NumPut(Offset_Y:=(Height-GWR_Height)//2,RECTPlus,20,"Int")
Return &RECTPlus
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;