Dear teadrinker,
Thank you very very much for your answers regarding the
TWO codes, CODE 1 and CODE 2, i was referring which are the following:
Note:
The only difference between CODE 1 and CODE 2 is the following:
Under SaveToImageFile FUNCTION, we substitute the variable name hBitmap to hBM, and pBitmap to pBM
CODE 1:
Code: Select all
F2:: ; press F2 to save screenshot
hBM := ""
hBM := GDI_CaptureScreen( 0, 0, A_ScreenWidth, A_ScreenHeight )
SaveToImageFile(hBM, A_ScriptDir . "\ScreenshotImage.jpg", 100)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
F3:: ; press F3 to load screenshot to clipboard
GDI_CaptureScreenToClipboard(0, 0, A_ScreenWidth, A_ScreenHeight)
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen(X, Y, W, H) {
static flags := (SRCCOPY := 0x00CC0020) | (CAPTUREBLT := 0x40000000)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
hObj := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", flags)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", hObj, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hBM
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SaveToImageFile(hBitmap, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBitmap := gdip.CreateBitmapFromHBITMAP(hBitmap)
gdip.SaveBitmap(pBitmap, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBitmap)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBitmap, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBitmap, "Ptr", Palette, "PtrP", pBitmap)
return pBitmap
}
SaveBitmap(pBitmap, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBitmap, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBitmap, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBitmap, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBitmap, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBitmap) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreenToClipboard( X, Y, W, H) {
Static SizeOfDIB := A_PtrSize = 8 ? 104 : 84 ; DIBSECTION
Static SizeOfBM := A_PtrSize = 8 ? 32 : 24 ; BITMAP
Static SizeOfBIH := 40 ; BITMAPINFOHEADER
Static OffBits := A_PtrSize = 8 ? 24 : 20 ; BITMAP -> bmBits
Static OffSize := A_PtrSize = 8 ? 52 : 44 ; BITMAPINFOHEADER -> biSizeImage
Local
hDC := DllCall("GetDC", "Ptr", 0, "UPtr")
cDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "UPtr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "UPtr")
hBM := DllCall("CopyImage", "Ptr", hBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
oBM := DllCall("SelectObject", "Ptr", cDC, "Ptr", hBM, "UPtr")
DllCall("BitBlt", "Ptr", cDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", 0x40CC0020)
DllCall("SelectObject", "Ptr", cDC, "Ptr", oBM)
DllCall("DeleteDC", "Ptr", tDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
VarSetCapacity(DIB, SizeOfDIB, 0) ; DIBSECTION
DllCall("GetObject", "Ptr", hBM, "Int", SizeOfDIB, "Ptr", &DIB)
Size := NumGet(DIB, OffSize, "UInt")
Bits := NumGet(DIB, OffBits, "UPtr")
hDIB := DllCall("GlobalAlloc", "UInt", 2, "UInt", SizeOfBIH + Size, "UPtr")
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "UPtr")
DllCall("RtlMoveMemory", "Ptr", pDIB, "Ptr", &DIB + SizeOfBM, "UInt", SizeOfBIH)
DllCall("RtlMoveMemory", "Ptr", pDIB + SizeOfBIH, "Ptr", Bits, "UInt", Size)
DllCall("GlobalUnlock", "Ptr", hDIB)
DllCall("DeleteObject", "Ptr", hBM)
DllCall("OpenClipboard", "Ptr", 0)
DllCall("EmptyClipboard")
DllCall("SetClipboardData", "UInt", 8, "Ptr", hDIB)
DllCall("CloseClipboard")
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
CODE 2:
Code: Select all
F2:: ; press F2 to save screenshot
hBM := ""
hBM := GDI_CaptureScreen( 0, 0, A_ScreenWidth, A_ScreenHeight )
SaveToImageFile(hBM, A_ScriptDir . "\ScreenshotImage.jpg", 100)
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Return
F3:: ; press F3 to load screenshot to clipboard
GDI_CaptureScreenToClipboard(0, 0, A_ScreenWidth, A_ScreenHeight)
Return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreen(X, Y, W, H) {
static flags := (SRCCOPY := 0x00CC0020) | (CAPTUREBLT := 0x40000000)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "Ptr")
hMDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "Ptr")
hObj := DllCall("SelectObject", "Ptr", hMDC, "Ptr", hBM, "Ptr")
DllCall("BitBlt", "Ptr", hMDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", flags)
DllCall("SelectObject", "Ptr", hMDC, "Ptr", hObj, "Ptr")
DllCall("DeleteDC", "Ptr", hMDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
Return hBM
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SaveToImageFile(hBM, destImageFilePath, jpegQuality := 75) {
gdip := new GDIplus()
pBM := gdip.CreateBitmapFromHBITMAP(hBM)
gdip.SaveBitmap(pBM, destImageFilePath, jpegQuality)
gdip.DisposeImage(pBM)
}
class GDIplus {
__New() {
this.hLib := DllCall("LoadLibrary", "Str", "gdiplus", "Ptr")
VarSetCapacity(si, 8 + A_PtrSize*2, 0), si := Chr(1)
DllCall("gdiplus\GdiplusStartup", "PtrP", pToken, "Ptr", &si, "Ptr", 0)
this.token := pToken
}
__Delete() {
DllCall("gdiplus\GdiplusShutdown", "Ptr", this.token)
DllCall("FreeLibrary", "Ptr", this.hLib)
}
CreateBitmapFromHBITMAP(hBM, Palette=0) {
DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr", hBM, "Ptr", Palette, "PtrP", pBM)
return pBM
}
SaveBitmap(pBM, ByRef info, Quality := 75, tobuff := "")
{
; info — if copying to buffer, then file extension, if copying to file, then file path
if tobuff
Extension := info
else
SplitPath, info,,, Extension
if Extension not in BMP,DIB,RLE,JPG,JPEG,JPE,JFIF,GIF,TIF,TIFF,PNG
return -1
DllCall("gdiplus\GdipGetImageEncodersSize", "UintP", nCount, "UintP", nSize)
VarSetCapacity(ci, nSize)
DllCall("gdiplus\GdipGetImageEncoders", "UInt", nCount, "UInt", nSize, "Ptr", &ci)
if !(nCount && nSize)
return -2
Loop, % nCount {
sString := StrGet(NumGet(ci, (idx := (48+7*A_PtrSize)*(A_Index-1))+32+3*A_PtrSize), "UTF-16")
if !InStr(sString, "*." Extension)
continue
pCodec := &ci+idx
break
}
if !pCodec
return -3
if RegExMatch(Extension, "i)^J(PG|PEG|PE|FIF)$") && Quality != 75 {
DllCall("gdiplus\GdipGetEncoderParameterListSize", "Ptr", pBM, "Ptr", pCodec, "UintP", nSize)
VarSetCapacity(EncoderParameters, nSize, 0)
DllCall("gdiplus\GdipGetEncoderParameterList", "Ptr", pBM, "Ptr", pCodec, "UInt", nSize, "Ptr", &EncoderParameters)
Loop, % NumGet(EncoderParameters, "UInt")
{
elem := (24+A_PtrSize)*(A_Index-1) + 4 + (pad := A_PtrSize = 8 ? 4 : 0)
if (NumGet(EncoderParameters, elem+16, "UInt") = 1) && (NumGet(EncoderParameters, elem+20, "UInt") = 6)
{
p := elem+&EncoderParameters-pad-4
NumPut(Quality, NumGet(NumPut(4, NumPut(1, p+0)+20, "UInt")), "UInt")
break
}
}
}
if !tobuff
E := DllCall("gdiplus\GdipSaveImageToFile", "Ptr", pBM, "WStr", info, "Ptr", pCodec, "UInt", p ? p : 0)
else {
DllCall( "ole32\CreateStreamOnHGlobal", "UInt", 0, "Int", 1, "PtrP", pStream )
if !E := DllCall( "gdiplus\GdipSaveImageToStream", "Ptr", pBM, "Ptr", pStream, "Ptr", pCodec, "UInt", p ? p : 0 ) {
DllCall( "ole32\GetHGlobalFromStream", "Ptr", pStream, "PtrP", hData )
pData := DllCall( "GlobalLock", "Ptr", hData, "Ptr" )
nSize := DllCall( "GlobalSize", "Ptr", hData, "Ptr" )
VarSetCapacity( info, 0), VarSetCapacity( info, nSize, 0 )
DllCall( "RtlMoveMemory", "Ptr", &info, "Ptr", pData, "UInt", nSize )
DllCall( "GlobalUnlock", "Ptr", hData )
DllCall( "GlobalFree", "Ptr", hData )
}
ObjRelease(pStream)
}
return E ? -4 : tobuff ? nSize : 0
}
DisposeImage(pBM) {
return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBM)
}
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GDI_CaptureScreenToClipboard( X, Y, W, H) {
Static SizeOfDIB := A_PtrSize = 8 ? 104 : 84 ; DIBSECTION
Static SizeOfBM := A_PtrSize = 8 ? 32 : 24 ; BITMAP
Static SizeOfBIH := 40 ; BITMAPINFOHEADER
Static OffBits := A_PtrSize = 8 ? 24 : 20 ; BITMAP -> bmBits
Static OffSize := A_PtrSize = 8 ? 52 : 44 ; BITMAPINFOHEADER -> biSizeImage
Local
hDC := DllCall("GetDC", "Ptr", 0, "UPtr")
cDC := DllCall("CreateCompatibleDC", "Ptr", hDC, "UPtr")
hBM := DllCall("CreateCompatibleBitmap", "Ptr", hDC, "Int", W, "Int", H, "UPtr")
hBM := DllCall("CopyImage", "Ptr", hBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
oBM := DllCall("SelectObject", "Ptr", cDC, "Ptr", hBM, "UPtr")
DllCall("BitBlt", "Ptr", cDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", hDC, "Int", X, "Int", Y, "UInt", 0x40CC0020)
DllCall("SelectObject", "Ptr", cDC, "Ptr", oBM)
DllCall("DeleteDC", "Ptr", tDC)
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC)
VarSetCapacity(DIB, SizeOfDIB, 0) ; DIBSECTION
DllCall("GetObject", "Ptr", hBM, "Int", SizeOfDIB, "Ptr", &DIB)
Size := NumGet(DIB, OffSize, "UInt")
Bits := NumGet(DIB, OffBits, "UPtr")
hDIB := DllCall("GlobalAlloc", "UInt", 2, "UInt", SizeOfBIH + Size, "UPtr")
pDIB := DllCall("GlobalLock", "Ptr", hDIB, "UPtr")
DllCall("RtlMoveMemory", "Ptr", pDIB, "Ptr", &DIB + SizeOfBM, "UInt", SizeOfBIH)
DllCall("RtlMoveMemory", "Ptr", pDIB + SizeOfBIH, "Ptr", Bits, "UInt", Size)
DllCall("GlobalUnlock", "Ptr", hDIB)
DllCall("DeleteObject", "Ptr", hBM)
DllCall("OpenClipboard", "Ptr", 0)
DllCall("EmptyClipboard")
DllCall("SetClipboardData", "UInt", 8, "Ptr", hDIB)
DllCall("CloseClipboard")
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Sorry, but because i am not a programmer, i will kindly request you dear teadrinker to clarify me
your last 3 answers, in order to ensure my correct understanding:
Answer 1:
The DeleteObject() function should be used by hBitmap when hBitmap has been created and is no longer needed. Failure to use DeleteObject() in this case will result in a memory leak.
So regarding BOTH the above TWO codes,
CODE 1 & CODE 2, the DeleteObject() is correctly used in BOTH CODES, so i must not worry for any memory leak, please?
Answer 2:
No, the variable name doesn't matter.
Considering the CODE 2 above, there are exist THREE DIFFERENT VARIABLES with the same name, the following:
(i)Under
F2:: ==> hBM variable
(ii)Under
GDI_CaptureScreen ==> hBM variable
(iii)Under
SaveToImageFile ==> hBM variable
Now, the reason you answer that the variable name does not matter, it is because the (i) is the ONLY one variable in the "MAIN" code of the script, while the (ii) and (iii) are variables that BELONG to functions which are something like INDEPENTED from the MAIN script, that is why there is no CONFLICT of the THREE different variables that have the same name.
Do i understand this matter correct, please?
Answer 3:
The variable name that was chosen to save hBitmap when it was created must be used.
I understand that you are referring to the "first" variable under ==>
F2:: ==> hBM variable
So, in BOTH
CODE 1 & CODE 2, the correct line must be:
Code: Select all
DllCall("DeleteObject", "Ptr", hBM) ; Clean-up
Do i understand this matter correct, please?
Once again, i want to say a BIG THANK you dear teadrinker for your helping us to learning!