http://topic.csdn.net/u/20090407/08/409d040a-1620-47b9-8472-d7001ed26a42.html
这个帖子我以为完结了 
结果现在发现,截取出来是黑屏的代码 
http://www.52delphi.com/list.asp?ID=597  用的就是这上面的代码。
谁出来 解决下 200分啦  说是只要锁定加速功能就可以或者缓冲区 
看了下SDK一头雾水 。
不要大幅度代码一共下怎么锁的  或者怎么 暂时关闭加速功能就行啦 3Q  

解决方案 »

  1.   

    DirectX截屏函数 Dx9实现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实现: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;
    ---------------------------------------------------
      

  2.   

    NF3 有什么好办法吗? 好像DELPHI 的高手不出现指点啊  呼唤高手啊
      

  3.   

    截图不出现黑屏,我可以给你解决,不过我的解决办法不用写一句代码,与DELPHI无关,不知道你承诺给200分是否能接受此方法?
      

  4.   

    在建立设备时,TD3DPresentParameters.Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER,这样才可获取背景缓存并锁住获取数据。
    下面是截图自己应用程序屏幕的代码,原理应该一样。
    unit MainFrm;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Direct3D9, D3DX9;const
      VERTEX_FVF = D3DFVF_XYZ or D3DFVF_DIFFUSE;
      
    type
      TVertex = packed record
        x, y, z: Single;
        color: DWORD;
      end;  PVertices = ^TVertices;
      TVertices = array[0..2] of TVertex;  TMainForm = class(TForm)
        procedure FormKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
      private
        FDirect3D: IDirect3D9;
        FD3DDevice: IDirect3DDevice9;
        FVertexBuf: IDirect3DVertexBuffer9;
        FKeyDown: Boolean;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure AppIdle(Sender: TObject; var Done: Boolean);
        procedure GetScreen;
      end;var
      MainForm: TMainForm;implementation{$R *.dfm}{ TMainForm }constructor TMainForm.Create(AOwner: TComponent);
    var
      pa: TD3DPresentParameters;
      matProj, matView: TD3DXMatrix;
      eye, at, up: TD3DVector;
      vertices: PVertices;
    begin
      inherited;
      FDirect3D := Direct3DCreate9(D3D_SDK_VERSION);
      if not Assigned(FDirect3D) then
      begin
        Application.MessageBox('Create Direct3D Failure', 'Error', MB_OK or MB_ICONERROR);
        Application.Terminate;
      end;  ZeroMemory(@pa, SizeOf(pa));
      pa.SwapEffect := D3DSWAPEFFECT_FLIP;
      pa.hDeviceWindow := Handle;
      pa.Windowed := True;
      pa.EnableAutoDepthStencil := True;
      pa.AutoDepthStencilFormat := D3DFMT_D16;
      pa.Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;  FDirect3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Handle, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
        @pa, FD3DDevice);  if not Assigned(FD3DDevice) then
      begin
        Application.MessageBox('Create Direct3DDevice Failure', 'Error', MB_OK or MB_ICONERROR);
        Application.Terminate;
      end;  FD3DDevice.CreateVertexBuffer(SizeOf(TVertex) * 3, 0, VERTEX_FVF, D3DPOOL_DEFAULT, FVertexBuf, nil);
      if not Assigned(FVertexBuf) then
      begin
        Application.MessageBox('Create Vertex Buffer Failure', 'Error', MB_OK or MB_ICONERROR);
        Application.Terminate;
      end;  D3DXMatrixPerspectiveFovRH(matProj, PI / 2, ClientWidth / ClientHeight, 1, 1000);
      eye := D3DXVector3(0, 0, 5);
      at := D3DXVector3(0, 0, 0);
      up := D3DXVector3(0, 1, 0);
      D3DXMatrixLookAtRH(matView, eye, at, up);
      FD3DDevice.SetTransform(D3DTS_PROJECTION, matProj);
      FD3DDevice.SetTransform(D3DTS_VIEW, matView);
      FD3DDevice.SetRenderState(D3DRS_LIGHTING, iFalse);
      FD3DDevice.SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
      
      FVertexBuf.Lock(0, 0, Pointer(vertices), 0);
      vertices[0].x := -1; vertices[0].y := -1; vertices[0].z := 0; vertices[0].color := $FFFF0000;
      vertices[1].x :=  1; vertices[1].y := -1; vertices[1].z := 0; vertices[1].color := $FF00FF00;
      vertices[2].x :=  0; vertices[2].y :=  1; vertices[2].z := 0; vertices[2].color := $FF0000FF;
      FVertexBuf.Unlock;  Application.OnIdle := AppIdle;
    end;destructor TMainForm.Destroy;
    begin
      FVertexBuf := nil;
      FD3DDevice := nil;
      FDirect3D := nil;
      inherited;
    end;procedure TMainForm.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      FKeyDown := True;
    end;procedure TMainForm.AppIdle(Sender: TObject; var Done: Boolean);
    var
      matWorld: TD3DMatrix;
    begin
      D3DXMatrixIdentity(matWorld);
      FD3DDevice.SetTransform(D3DTS_WORLD, matWorld);  FD3DDevice.Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER, $FF000000, 1, 0);
      if Succeeded(FD3DDevice.BeginScene) then
      begin
        FD3DDevice.SetFVF(VERTEX_FVF);
        FD3DDevice.SetStreamSource(0, FVertexBuf, 0, SizeOf(TVertex));
        FD3DDevice.DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);
        FD3DDevice.EndScene;
        FD3DDevice.SetStreamSource(0, nil, 0, 0);
        FD3DDevice.Present(nil, nil, Handle, nil);
      end;  if FKeyDown then
      begin
        GetScreen;
        FKeyDown := False;
      end;  Done := False;
    end;procedure TMainForm.GetScreen;
    type
      TColor4 = packed record
        b, g, r, a: Byte;
      end;
      PColor4Array = ^TColor4Array;
      TColor4Array = array[0..0] of TColor4;  TColor3 = packed record
        b, g, r: Byte;
      end;
      PColor3Array = ^TColor3Array;
      TColor3Array = array[0..0] of TColor3;var
      i, j: Integer;
      bf: IDirect3DSurface9;
      r: TRect;
      lr: TD3DLockedRect;
      bmp: TBitmap;
      src: PColor4Array;
      dest: PColor3Array;
    begin
      r := Rect(0, 0, ClientWidth, ClientHeight);
      FD3DDevice.GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, bf);
      bf.LockRect(lr, nil, D3DLOCK_READONLY);
      bmp := TBitmap.Create;
      bmp.Width := ClientWidth;
      bmp.Height := ClientHeight;
      bmp.PixelFormat := pf24Bit;
      for i := 0 to ClientHeight - 1 do
      begin
        src := lr.pBits;
        dest := bmp.ScanLine[i];
        for j := 0 to ClientWidth - 1 do
        begin
          dest[j].b := src[j].b;
          dest[j].g := src[j].g;
          dest[j].r := src[j].r;
        end;
        lr.pBits := Pointer(Integer(lr.pBits) + lr.Pitch);
      end;
      bf.UnlockRect;
      bf := nil;
      bmp.SaveToFile(ExtractFilePath(Application.ExeName) + 'Screen.bmp');
      bmp.Free;
    end;end.
      

  5.   

    你必须hook IDirect3D.CreateDevice方法,如果应用程序是别人的。
      

  6.   

    把email地址给我,我发我做的例子给你。
      

  7.   

    後台截圖的代碼例子也發給我一份吧。謝謝
    QQ120052086,[email protected]
      

  8.   

    经过2个月 查阅了大量老外的博客 已经能对directx窗口后台截图  利用api hook 可以对directx窗口截图,窗口移动到屏幕外,或者showwindow(hwnd, sw_hide) 都能录到,窗口最小化是不行的 。在网上查阅到的2-3个例子都是需要在本程序使用DetourCreateProcessWithDll之类的,由本程序启动需要截屏的directx程序,截获Direct3DCreate9 得到Direct3D对象的接口指针 -》CreateDevice   得到d3ddevice 这样局限性比较大。我的程序可以直接挂钩已经在执行的进程,直接截屏。
      

  9.   

    Win7 下DX后台截图 其实很简单的! XP下呢..反而有点不好弄了! 不用什么Hook 的! 
    不能最小化,其他不限