想了一天的问题,请熟悉DirectShow的高手进来(100分)

  • 主题发起人 主题发起人 dira
  • 开始时间 开始时间
D

dira

Unregistered / Unconfirmed
GUEST, unregistred user!
如何在ACTIVEFORM中使用DirectShow来截图
 
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:DDSURFACEDESC;
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:DDSURFACEDESC;
nWidth,nHeigh:integer;
nPitch,dwDataSize:DWORD;
pSurface,pDest:Pchar;
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.
 
TScreenBuf中_corlorMap是个什么类型?网上搜了一通没搜着,有高手看得出来的话请跟贴
 
谢谢老兄的回答,138soft老久没上得去了。。。
 
你研究一下dspack就行了,里面有个TSampleGrabber控件,主要是用了ISampleGrabber接口的
 
TSampleGrabber在EXE中是好的,但在OCX中SampleGrabber在GetCurrentBuffer出错,只知道返回值不是S_OK,没办法进一步调试
 
解决问题了,可以使用VideoWindow1.VMRGetBitmap,感觉jingtao兄给的代码是屏幕截图的例子,不过很感谢
 
后退
顶部