我已根据此C++ example构建了以下代码的一部分,目标是在捕获时不显示主要表单的情况下制作屏幕截图。
我的麻烦是因为我通过以下代码获取黑屏:
function MagImageScalingCallback(hwnd: hwnd; srcdata: Pointer;
srcheader: MAGIMAGEHEADER; destdata: Pointer; destheader: MAGIMAGEHEADER;
unclipped: TRect; clipped: TRect; dirty: HRGN): BOOL; stdcall;
var
lpbmih: TBitmapInfoHeader;
lpbmi: TBitmapInfo;
aBitmap: HBITMAP;
aDC: HDC;
bmp: TBitmap;
begin
Fillchar(lpbmih, SizeOf(lpbmih), 0);
lpbmih.biSize := SizeOf(lpbmih);
lpbmih.biWidth := srcheader.width;
lpbmih.biHeight := srcheader.height;
lpbmih.biPlanes := 1;
lpbmih.biBitCount := Floor(lpbmih.biSizeImage / lpbmih.biHeight /
lpbmih.biWidth * 8);
lpbmih.biCompression := BI_RGB;
Fillchar(lpbmi, SizeOf(lpbmi), 0);
lpbmi.bmiHeader.biSize := SizeOf(lpbmi.bmiHeader);
lpbmi.bmiHeader.biWidth := srcheader.width;
lpbmi.bmiHeader.biHeight := srcheader.height;
lpbmi.bmiHeader.biPlanes := 1;
lpbmi.bmiHeader.biBitCount :=
Floor(lpbmi.bmiHeader.biSizeImage / lpbmi.bmiHeader.biHeight /
lpbmi.bmiHeader.biWidth * 8);
lpbmi.bmiHeader.biCompression := BI_RGB;
aDC := GetWindowDC(hwnd);
bmp := TBitmap.Create;
aBitmap := 0;
try
aBitmap := CreateDIBitmap(aDC, lpbmih, 0, nil, lpbmi, DIB_RGB_COLORS);
bmp.handle := aBitmap;
bmp.SaveToFile('c:\screen.bmp');
finally
DeleteObject(aBitmap);
DeleteDC(aDC);
bmp.Free;
end;
Result := True;
end;
这是我的完整代码:
var
Form1: TForm1;
implementation
uses
Unit3, Magnification;
{$R *.dfm}
function MagImageScalingCallback(hwnd: hwnd; srcdata: Pointer;
srcheader: MAGIMAGEHEADER; destdata: Pointer; destheader: MAGIMAGEHEADER;
unclipped: TRect; clipped: TRect; dirty: HRGN): BOOL; stdcall;
var
lpbmih: TBitmapInfoHeader;
lpbmi: TBitmapInfo;
aBitmap: HBITMAP;
aDC: HDC;
bmp: TBitmap;
begin
Fillchar(lpbmih, SizeOf(lpbmih), 0);
lpbmih.biSize := SizeOf(lpbmih);
lpbmih.biWidth := srcheader.width;
lpbmih.biHeight := srcheader.height;
lpbmih.biPlanes := 1;
lpbmih.biBitCount := Floor(lpbmih.biSizeImage / lpbmih.biHeight /
lpbmih.biWidth * 8);
lpbmih.biCompression := BI_RGB;
Fillchar(lpbmi, SizeOf(lpbmi), 0);
lpbmi.bmiHeader.biSize := SizeOf(lpbmi.bmiHeader);
lpbmi.bmiHeader.biWidth := srcheader.width;
lpbmi.bmiHeader.biHeight := srcheader.height;
lpbmi.bmiHeader.biPlanes := 1;
lpbmi.bmiHeader.biBitCount :=
Floor(lpbmi.bmiHeader.biSizeImage / lpbmi.bmiHeader.biHeight /
lpbmi.bmiHeader.biWidth * 8);
lpbmi.bmiHeader.biCompression := BI_RGB;
aDC := GetWindowDC(hwnd);
bmp := TBitmap.Create;
aBitmap := 0;
try
aBitmap := CreateDIBitmap(aDC, lpbmih, 0, nil, lpbmi, DIB_RGB_COLORS);
bmp.handle := aBitmap;
bmp.SaveToFile('c:\screen.bmp');
finally
DeleteObject(aBitmap);
DeleteDC(aDC);
bmp.Free;
end;
Result := True;
end;
procedure MagScreenShot;
var
desktop, hwndMag: hwnd;
desktoprect, sourceRect: TRect;
filterList: THWNDArray;
m_ScreenX, m_ScreenY, m_ScreenT, m_ScreenL: Integer;
begin
if not Form3.Showing then
Form3.Show;
desktop := GetDesktopWindow;
GetWindowRect(desktop, desktoprect);
m_ScreenT := desktoprect.Top;
m_ScreenL := desktoprect.Left;
m_ScreenX := desktoprect.right;
m_ScreenY := desktoprect.bottom;
if (not MagInitialize) then
begin
Application.MessageBox('Init magnification failed', 'Error',
mb_Ok + mb_IconError);
Exit;
end;
hwndMag := CreateWindow(WC_MAGNIFIER, 'MagnifierWindow',
WS_CHILD or MS_SHOWMAGNIFIEDCURSOR or WS_VISIBLE, 0, 0, m_ScreenX,
m_ScreenY, Form1.handle, 0, hInstance, nil);
if (hwndMag = 0) then
begin
Application.MessageBox('MagnifierWindow creation failed', 'Error',
mb_Ok + mb_IconError);
Exit;
end;
if (not MagSetImageScalingCallback(hwndMag, MagImageScalingCallback)) then
begin
Application.MessageBox('Cannot set callback', 'Error',
mb_Ok + mb_IconError);
Exit;
end;
try
filterList[0] := Form3.handle;
except
end;
if (not MagSetWindowFilterList(hwndMag, MW_FILTERMODE_EXCLUDE, 1,
@filterList[0])) then
begin
Application.MessageBox('Cannot exclude main window', 'Error',
mb_Ok + mb_IconError);
Exit;
end;
sourceRect.Top := m_ScreenT;
sourceRect.Left := m_ScreenL;
sourceRect.right := m_ScreenX;
sourceRect.bottom := m_ScreenY;
if (not MagSetWindowSource(hwndMag, sourceRect)) then
begin
Application.MessageBox('Cannot set source to MagnifierWindow', 'Error',
mb_Ok + mb_IconError);
Exit;
end;
{ if (not MagUninitialize) then
begin
Application.MessageBox('Finalize magnification failed', 'Error',
mb_Ok + mb_IconError);
Exit;
end; }
end;
procedure TForm1.tmr1Timer(Sender: TObject);
begin
MagScreenShot;
end;
放大单位:
unit Magnification;
{$ALIGN ON}
{$MINENUMSIZE 4}
interface
uses
Windows;
const
// Magnifier Class Name
WC_MAGNIFIERA: AnsiString = 'Magnifier';
WC_MAGNIFIERW: WideString = 'Magnifier';
WC_MAGNIFIER = 'Magnifier';
// Magnifier Window Styles
MS_SHOWMAGNIFIEDCURSOR = $0001;
MS_CLIPAROUNDCURSOR = $0002;
MS_INVERTCOLORS = $0004;
// Filter Modes
MW_FILTERMODE_EXCLUDE = 0;
MW_FILTERMODE_INCLUDE = 1;
type
tagMAGTRANSFORM = record
v: array[1..3, 1..3] of Single;
end;
MAGTRANSFORM = tagMAGTRANSFORM;
TMagTransform = tagMAGTRANSFORM;
PMagTransform = ^TMagTransform;
tagMAGIMAGEHEADER = record
width: UINT;
height: UINT;
format: TGUID;
stride: UINT;
offset: UINT;
cbSize: UINT;
end;
MAGIMAGEHEADER = tagMAGIMAGEHEADER;
TMagImageHeader = tagMAGIMAGEHEADER;
PMagImageHeader = ^TMagImageHeader;
tagMAGCOLOREFFECT = record
transform: array[1..5, 1..5] of Single;
end;
MAGCOLOREFFECT = tagMAGCOLOREFFECT;
TMagColorEffect = tagMAGCOLOREFFECT;
PMagColorEffect = ^TMagColorEffect;
TMagImageScalingCallback = function (hwnd: HWND; srcdata: Pointer;
srcheader: MAGIMAGEHEADER; destdata: Pointer; destheader: MAGIMAGEHEADER;
unclipped: TRect; clipped: TRect; dirty: HRGN): BOOL; stdcall;
THWNDArray = array[0..0] of HWND;
PHWNDArray = ^THWNDArray;
// Public Functions
function MagInitialize(): BOOL; stdcall;
function MagUninitialize(): BOOL; stdcall;
function MagSetWindowSource(hwnd: HWND; rect: TRect): BOOL; stdcall;
function MagGetWindowSource(hwnd: HWND; var Rect: TRect): BOOL; stdcall;
function MagSetWindowTransform(hwnd: HWND; var Transform: TMagTransform): BOOL; stdcall;
function MagGetWindowTransform(hwnd: HWND; var Transform: TMagTransform): BOOL; stdcall;
function MagSetWindowFilterList(hwnd: HWND; dwFilterMode: DWORD;
count: Integer; pHWND: PHWNDArray): BOOL; stdcall;
function MagGetWindowFilterList(hwnd: HWND; var dwFilterMode: DWORD;
count: Integer; pHWND: PHWNDArray): Integer; stdcall;
function MagSetImageScalingCallback(hwnd: HWND;
MagImageScalingCallback: TMagImageScalingCallback): BOOL; stdcall;
// MagImageScalingCallback WINAPI MagGetImageScalingCallback(HWND hwnd );
function MagSetColorEffect(hwnd: HWND; var Effect: TMagColorEffect): BOOL; stdcall;
function MagGetColorEffect(hwnd: HWND; var Effect: TMagColorEffect): BOOL; stdcall;
implementation
const
MagnificationDll = 'Magnification.dll';
function MagInitialize; external MagnificationDll name 'MagInitialize';
function MagUninitialize; external MagnificationDll name 'MagUninitialize';
function MagSetWindowSource; external MagnificationDll name 'MagSetWindowSource';
function MagGetWindowSource; external MagnificationDll name 'MagGetWindowSource';
function MagSetWindowTransform; external MagnificationDll name 'MagSetWindowTransform';
function MagGetWindowTransform; external MagnificationDll name 'MagGetWindowTransform';
function MagSetWindowFilterList; external MagnificationDll name 'MagSetWindowFilterList';
function MagGetWindowFilterList; external MagnificationDll name 'MagGetWindowFilterList';
function MagSetImageScalingCallback; external MagnificationDll name 'MagSetImageScalingCallback';
function MagSetColorEffect; external MagnificationDll name 'MagSetColorEffect';
function MagGetColorEffect; external MagnificationDll name 'MagGetColorEffect';
end.
版:
我最近在下面尝试了这个替代方案,但是生成了一个无效的bmp文件。
function SaveBitmapToFile(bitmap: PBITMAP; lpFileName: PChar;
lpBuf: PChar): BOOL;
var
dwWritten: DWORD;
bmfHdr: BITMAPFILEHEADER;
bi: BITMAPINFOHEADER;
fh: THANDLE;
begin
Result := False;
fh := INVALID_HANDLE_VALUE;
bi.biSize := sizeof(BITMAPINFOHEADER);
bi.biWidth := bitmap^.bmWidth;
bi.biHeight := bitmap^.bmHeight;
bi.biPlanes := 1;
bi.biBitCount := bitmap^.bmBitsPixel * 8;
bi.biCompression := BI_RGB;
bi.biSizeImage := 0;
bi.biXPelsPerMeter := 0;
bi.biYPelsPerMeter := 0;
bi.biClrUsed := 0;
bi.biClrImportant := 0;
fh := CreateFile(lpFileName, GENERIC_WRITE, 0, Nil, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
if (fh = INVALID_HANDLE_VALUE) then
Exit;
bmfHdr.bfType := $4D42; // "BM"
bmfHdr.bfSize := sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
bitmap^.bmWidth * bitmap^.bmHeight * bitmap^.bmBitsPixel;
bmfHdr.bfReserved1 := 0;
bmfHdr.bfReserved2 := 0;
bmfHdr.bfOffBits := DWORD(sizeof(BITMAPFILEHEADER)) +
DWORD(sizeof(BITMAPINFOHEADER));
WriteFile(fh, PChar(@bmfHdr)^, sizeof(BITMAPFILEHEADER), dwWritten, nil);
WriteFile(fh, PChar(@bi)^, sizeof(BITMAPINFOHEADER), dwWritten, nil);
WriteFile(fh, PChar(lpBuf)^, bitmap^.bmWidth * bitmap^.bmHeight *
bitmap^.bmBitsPixel, dwWritten, nil);
FlushFileBuffers(fh);
CloseHandle(fh);
Result := true;
end;
function MagImageScalingCallback(hwnd: hwnd; srcdata: Pointer;
srcheader: MAGIMAGEHEADER; destdata: Pointer; destheader: MAGIMAGEHEADER;
unclipped: TRect; clipped: TRect; dirty: HRGN): BOOL; stdcall;
var
b: BITMAPINFO;
hBitmap, hOld: Winapi.Windows.HBITMAP;
bb: bitmap;
hp: THANDLE;
hDC, hcDC: Winapi.Windows.hDC;
lpBuf: PChar;
begin
hDC := GetDC(hwnd);
hcDC := CreateCompatibleDC(hDC);
hBitmap := CreateCompatibleBitmap(hDC, srcheader.width, srcheader.height);
hOld := Winapi.Windows.HBITMAP(SelectObject(hcDC, hBitmap));
BitBlt(hcDC, 0, 0, srcheader.width, srcheader.height, hDC, 0, 0, SRCCOPY);
bb.bmWidth := srcheader.width;
bb.bmHeight := srcheader.height;
bb.bmPlanes := 1;
bb.bmWidthBytes := bb.bmWidth * 3;
bb.bmBitsPixel := 3;
bb.bmType := 0;
b.bmiHeader.biSize := sizeof(BITMAPINFOHEADER);
b.bmiHeader.biHeight := srcheader.height;
b.bmiHeader.biWidth := srcheader.width;
b.bmiHeader.biSizeImage := srcheader.cbSize;
b.bmiHeader.biPlanes := 1;
b.bmiHeader.biBitCount := 3 * 8;
b.bmiHeader.biCompression := BI_RGB;
b.bmiHeader.biSizeImage := srcheader.cbSize;
b.bmiHeader.biXPelsPerMeter := 0;
b.bmiHeader.biYPelsPerMeter := 0;
b.bmiHeader.biClrUsed := 0;
b.bmiHeader.biClrImportant := 0;
b.bmiColors[0].rgbBlue := 8;
b.bmiColors[0].rgbGreen := 8;
b.bmiColors[0].rgbRed := 8;
b.bmiColors[0].rgbReserved := 0;
hp := GetProcessHeap;
lpBuf := PChar(HeapAlloc(hp, HEAP_ZERO_MEMORY, bb.bmHeight * bb.bmWidth * 4));
GetDIBits(hcDC, hBitmap, 0, srcheader.height, lpBuf, b, DIB_RGB_COLORS);
SaveBitmapToFile(@bb, 'c:\screen.bmp', lpBuf);
ReleaseDC(hwnd, hDC);
DeleteDC(hcDC);
DeleteObject(hBitmap);
DeleteObject(hOld);
HeapFree(hp, 0, lpBuf);
Result := true;
end;
答案 0 :(得分:1)
biBitCount
字段填充为零,但必须包含32之类的值 - 从源数据中获取它。此外,您不需要填充标题两次。
CreateDIBitmap
函数调用不使用指向数据的指针(srcdata
)。设置参数CBM_INIT
和指向数据的指针。快速制作的工作示例:
var
lpbmi: TBitmapInfo;
bmp: TBitmap;
SrcData: PByteArray;
i: Integer;
abitmap:HBitmap;
begin
GetMem(SrcData, 256 * 256 * 4);
for i := 0 to 256 * 256 - 1 do
PInteger(@SrcData[i * 4])^ := Random($1000000);
Fillchar(lpbmi, SizeOf(lpbmi), 0);
lpbmi.bmiHeader.biSize := SizeOf(lpbmi.bmiHeader);
lpbmi.bmiHeader.biWidth := 256;
lpbmi.bmiHeader.biHeight := 256;
lpbmi.bmiHeader.biPlanes := 1;
lpbmi.bmiHeader.biBitCount := 32;
lpbmi.bmiHeader.biCompression := BI_RGB;
bmp := Tbitmap.Create;
aBitmap := 0;
try
aBitmap := CreateDIBitmap(GetDC(0), lpbmi.bmiHeader, CBM_INIT, SrcData, lpbmi, DIB_RGB_COLORS);
bmp.handle := aBitmap;
Canvas.Draw(0, 0, bmp);
finally
DeleteObject(aBitmap);
bmp.Free;
end;
end;