Easy...
unit Unit3;
interface
uses
Windows, Messages,DirectDraw, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,Unit2;
type
LPDIRECTDRAW=IDirectDraw;
LPDIRECTDRAWSURFACE=IDirectDrawSurface;
TDXCapture=class
private
lpDD:LPDIRECTDRAW;
lpDDSPrime:LPDIRECTDRAWSURFACE;
lpDDSBack:LPDIRECTDRAWSURFACE;
lpSurf:LPDIRECTDRAWSURFACE;
public
function Capture(const rc:TRect;pScreenBuf:TScreenBuf):BOOL;
function Initialize():BOOL;
constructor Create();
destructor Destroy;
override;
end;
implementation
uses
Unit1;
{ TDXCapture }
function TDXCapture.Initialize: BOOL;
var
hr:HRESULT;
DDSdesc,DDSdesc2
DSURFACEDESC;
begin
Result:=False;
// 初始化directX
hr := DirectDrawCreate(0, lpDD, nil);
if (FAILED(hr)) then
Exit;
hr := lpDD.SetCooperativeLevel(0, DDSCL_NORMAL);
if (FAILED(hr)) then
Exit;
ZeroMemory(@DDSdesc, sizeof(DDSdesc));
DDSdesc.dwSize := sizeof(DDSdesc);
DDSdesc.dwFlags := DDSD_CAPS;
DDSdesc.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE;
hr := lpDD.CreateSurface(DDSdesc, lpDDSPrime, nil);
if (FAILED(hr)) then
Exit;
ZeroMemory(@DDSdesc, sizeof(DDSdesc));
DDSdesc.dwSize := sizeof(DDSdesc);
DDSdesc.dwFlags := DDSD_ALL;
hr := lpDDSPrime.GetSurfaceDesc(DDSdesc);
if (FAILED(hr)) then
Exit;
g_dwScreenWidth:=DDSdesc.dwWidth;
g_dwScreenHeight:=DDSdesc.dwHeight;
g_cmScreen.SetType(TColorType(DDSdesc.ddpfPixelFormat.dwRGBBitCount div 8));
ZeroMemory(@DDSdesc2, sizeof(DDSdesc2));
DDSdesc2.dwSize := sizeof(DDSdesc);
DDSdesc2.dwFlags := DDSD_CAPS or DDSD_HEIGHT or DDSD_WIDTH;
DDSdesc2.ddsCaps.dwCaps := DDSCAPS_OFFSCREENPLAIN or DDSCAPS_SYSTEMMEMORY ;
DDSdesc2.dwHeight := DDSdesc.dwHeight;
DDSdesc2.dwWidth := DDSdesc.dwWidth;
hr := lpDD.CreateSurface(DDSdesc2, lpDDSBack, nil);
if (FAILED(hr))then
Exit;
Result:=TRUE;
end;
function TDXCapture.Capture(const rc: TRect;
pScreenBuf: TScreenBuf): BOOL;
var
hr:HRESULT;
surfdesc
DSURFACEDESC;
nWidth,nHeigh:integer;
nPitch,dwDataSize
WORD;
pSurface,pDest
char;
i:integer;
begin
Result:= FALSE;
hr:=0;
pScreenBuf._rc:=rc;
hr := lpDDSBack.BltFast(rc.left,rc.top,lpDDSPrime,@pScreenBuf._rc,DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT);
if (FAILED(hr)) then
Exit;
ZeroMemory(@surfdesc, sizeof(surfdesc));
surfdesc.dwSize := sizeof(surfdesc);
hr := lpDDSBack.Lock(@pScreenBuf._rc, surfdesc, DDLOCK_READONLY or DDLOCK_WAIT or DDLOCK_SURFACEMEMORYPTR , 0);
//hr = lpDDSPrime->Lock(&pScreenBuf->_rc, &surfdesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR /*|DDLOCK_NOSYSLOCK*/, NULL);
if (FAILED(hr)) then
Exit;
pScreenBuf._corlorMap.SetType(TColorType(surfdesc.ddpfPixelFormat.dwRGBBitCount div 8));
nWidth:=rc.right-rc.left;
nHeigh:=rc.bottom-rc.top;
nPitch:=nWidth * pScreenBuf._corlorMap.pitch();
dwDataSize:=nHeigh * nPitch ;
//surfdesc.dwHeight*surfdesc.lPitch;
if (pScreenBuf._bufSeize<dwDataSize) then
begin
if (pScreenBuf._bufSeize<>0) then
FreeMem(pScreenBuf._pdata);
GetMem(pScreenBuf._pdata,dwDataSize);
pScreenBuf._bufSeize:=dwDataSize;
end;
pScreenBuf._size:=dwDataSize;
//copy data to buf
if (nWidth=surfdesc.dwWidth) then
begin
CopyMemory(pScreenBuf._pdata,surfdesc.lpSurface,dwDataSize);
end
else
begin
pSurface:=Pchar(surfdesc.lpSurface);
pDest:=pScreenBuf._pdata;
for i:=0 to nHeigh-1do
begin
CopyMemory(pDest,pSurface,nPitch);
pSurface:=pSurface+surfdesc.lPitch;
pDest:=pDest+nPitch;
end;
end;
// unlock the primary surface
//lpDDSPrime->Unlock(surfdesc.lpSurface);
lpDDSBack.Unlock(surfdesc.lpSurface);
Result:= TRUE;
end;
constructor TDXCapture.Create;
begin
inherited Create;
end;
destructor TDXCapture.Destroy;
begin
inherited Destroy;
end;
end.