天天看点

Delphi中使用DirectX截屏函数

 procedure CaptureScreen(Const FileName: string);

var

BitsPerPixel: Byte;

pD3D: IDirect3D9;

pSurface: IDirect3DSurface9;

g_pD3DDevice: IDirect3DDevice9;

D3DPP: TD3DPresentParameters;

ARect: TRect;

LockedRect: TD3DLockedRect;

BMP: TBitmap;

i, p: Integer;

begin

BitsPerPixel := GetDeviceCaps(Canvas.Handle, BITSPIXEL);

FillChar(d3dpp, SizeOf(d3dpp), 0);

D3DPP.Windowed := True;

D3DPP.Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

D3DPP.SwapEffect := D3DSWAPEFFECT_DISCARD;

D3DPP.BackBufferWidth := Screen.Width;

D3DPP.BackBufferHeight := Screen.Height;

D3DPP.BackBufferFormat := D3DFMT_X8R8G8B8;

pD3D := Direct3DCreate9(D3D_SDK_VERSION);

pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow,

D3DCREATE_SOFTWARE_VERTEXPROCESSING, @D3DPP, g_pD3DDevice);

g_pD3DDevice.CreateOffscreenPlainSurface(Screen.Width, Screen.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, pSurface, nil);

g_pD3DDevice.GetFrontBufferData(0, pSurface);

// use D3D to save surface. Notes: D3DX%ab.dll is required!

// D3DXSaveSurfaceToFile('Desktop.bmp', D3DXIFF_BMP, pSurface, nil, nil);

// use Bitmap to save surface

ARect := Screen.DesktopRect;

pSurface.LockRect(LockedRect, @ARect, D3DLOCK_NO_DIRTY_UPDATE or D3DLOCK_NOSYSLOCK or D3DLOCK_READONLY);

BMP := TBitmap.Create;

BMP.Width := Screen.Width;

BMP.Height := Screen.Height;

case BitsPerPixel of

8: BMP.PixelFormat := pf8bit;

16: BMP.PixelFormat := pf16bit;

24: BMP.PixelFormat := pf24bit;

32: BMP.PixelFormat := pf32bit;

end;

p := Cardinal(LockedRect.pBits);

for i := 0 to Screen.Height - 1 do

begin

CopyMemory(BMP.ScanLine[i], Ptr(p), Screen.Width * BitsPerPixel div 8);

p := p + LockedRect.Pitch;

end;

BMP.SaveToFile(FileName);

BMP.Free;

pSurface.UnlockRect;

end;

procedure CaptureScreen(const FileName: string;Const FileType: TD3DXImageFileFormat);

var

pD3D: IDirect3D9;

pSurface: IDirect3DSurface9;

g_pD3DDevice: IDirect3DDevice9;

D3DPP: TD3DPresentParameters;

begin

FillChar(d3dpp, SizeOf(d3dpp), 0);

D3DPP.Windowed := True;

D3DPP.Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

D3DPP.SwapEffect := D3DSWAPEFFECT_DISCARD;

D3DPP.BackBufferWidth := Screen.Width;

D3DPP.BackBufferHeight := Screen.Height;

D3DPP.BackBufferFormat := D3DFMT_X8R8G8B8;

pD3D := Direct3DCreate9(D3D_SDK_VERSION);

pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow,

D3DCREATE_SOFTWARE_VERTEXPROCESSING, @D3DPP, g_pD3DDevice);

g_pD3DDevice.CreateOffscreenPlainSurface(Screen.Width, Screen.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, pSurface, nil);

g_pD3DDevice.GetFrontBufferData(0, pSurface);

D3DX9.D3DXSaveSurfaceToFile(PChar(FileName),FileType,pSurface,nil,nil);

pSurface := nil;

g_pD3DDevice := nil;

pD3D := nil;

end;

传递两个参数,第一个参数指定为文件名,第二个参数指定为文件类型

支持7种类型

_D3DXIMAGE_FILEFORMAT = (

D3DXIFF_BMP {= 0},

D3DXIFF_JPG {= 1},

D3DXIFF_TGA {= 2},

D3DXIFF_PNG {= 3},

D3DXIFF_DDS {= 4},

D3DXIFF_PPM {= 5},

D3DXIFF_DIB {= 6}

);

再给一个使用dX8实现的,上面给的是用Dx9实现的函数

procedure CaptureScreen(const FileName: string;Const FileType: TD3DXImageFileFormat);

var

pD3D: IDirect3D8;

pSurface: IDirect3DSurface8;

g_pD3DDevice: IDirect3DDevice8;

D3DPP: TD3DPresentParameters;

begin

FillChar(d3dpp, SizeOf(d3dpp), 0);

D3DPP.Windowed := True;

D3DPP.Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

D3DPP.SwapEffect := D3DSWAPEFFECT_DISCARD;

D3DPP.BackBufferWidth := Screen.Width;

D3DPP.BackBufferHeight := Screen.Height;

D3DPP.BackBufferFormat := D3DFMT_X8R8G8B8;

pD3D := Direct3DCreate8(D3D_SDK_VERSION);

pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow,

D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DPP, g_pD3DDevice);

g_pD3DDevice.CreateImageSurface(Screen.Width, Screen.Height, D3DFMT_A8R8G8B8, pSurface);

g_pD3DDevice.GetFrontBuffer(pSurface);

D3DX8.D3DXSaveSurfaceToFile(PChar(FileName),FileType,pSurface,nil,nil);

pSurface := nil;

g_pD3DDevice := nil;

pD3D := nil;

end;

再给一个直接使用系统GDI实现的抓屏

procedure CaptureScreen(const FileName: string);overload;

var

nScreenWidth,nScreenHeight: integer;

ScreenDc,hCaptureDC: HDC;

bmp: TBitmap;

begin

nScreenWidth := GetSystemMetrics(SM_CXSCREEN);

nScreenHeight := GetSystemMetrics(SM_CYSCREEN);

ScreenDc := GetDC(GetDesktopWindow);

hCaptureDC := CreateCompatibleDC(ScreenDc);

bmp := TBitmap.Create;

bmp.Handle :=CreateCompatibleBitmap(ScreenDc,nScreenWidth, nScreenHeight);

SelectObject(hCaptureDC,bmp.Handle);

BitBlt(hCaptureDC,0,0,nScreenWidth,nScreenHeight,ScreenDc,0,0,SRCCOPY);

bmp.SaveToFile(fileName);

ReleaseDC(GetDesktopWindow,ScreenDc);

DeleteDC(hCaptureDC);

bmp.Free;

end;

通过上面这一步,我们可以很容易联想到用来抓取任何一个控件的表面图象,函数如下:

procedure CaptureControl(Control: TWinControl;const FileName: string);overload;

var

ControlWidth,ControlHeight: integer;

ControlDc,hCaptureDC: HDC;

bmp: TBitmap;

begin

ControlWidth := Control.ClientWidth;

ControlHeight := Control.ClientHeight;

ControlDc := GetDC(Control.Handle);

hCaptureDC := CreateCompatibleDC(ControlDc);

bmp := TBitmap.Create;

bmp.Handle :=CreateCompatibleBitmap(ControlDc,ControlWidth,ControlHeight);

SelectObject(hCaptureDC,bmp.Handle);

BitBlt(hCaptureDC,0,0,ControlWidth,ControlHeight,ControlDc,0,0,SRCCOPY);

bmp.SaveToFile(fileName);

ReleaseDC(GetDesktopWindow,ControlDc);

DeleteDC(hCaptureDC);

bmp.Free;

end;