1

DirectX (DX9) でデスクトップのスクリーンショットを取得し、すぐにフォームに (小さいサイズで) 描画しようとしています。

デバイスがいくつかのサーフェスと共に作成され、それらを画面にレンダリングできるように、DirectX を機能させています。F3F3Surf9_SSデスクトップのスクリーンショットを取得するために1 つのサーフェスを使用しています。

これが変数の宣言と初期化です

F3D3Surf9_SS : IDirect3DSurface9; //Surface SS
F3D3Surf9_A : IDirect3DSurface9;  //Surface A
F3D3Surf9_B : IDirect3DSurface9;  //Surface B

...

FDirect3D9.CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,Form1.Handle,
                        D3DCREATE_SOFTWARE_VERTEXPROCESSING,@D3DPresentParams,
                        FDirect3DDevice9);

FDirect3DDevice9.CreateOffscreenPlainSurface(1360,768,D3DFMT_X8R8G8B8,
                                             D3DPOOL_DEFAULT,F3D3Surf9_A,nil);

D3DXLoadSurfaceFromFile(F3D3Surf9_A,nil,nil,'D:\Images\Pillar.bmp',nil,
                        D3DX_DEFAULT,0,nil);

FDirect3DDevice9.CreateOffscreenPlainSurface(1360,768,D3DFMT_X8R8G8B8,
                                             D3DPOOL_DEFAULT,F3D3Surf9_B,nil);

D3DXLoadSurfaceFromFile(F3D3Surf9_B,nil,nil,'D:\Images\Niagra.bmp',nil,
                        D3DX_DEFAULT,0,nil);

FDirect3DDevice9.CreateOffscreenPlainSurface(Screen.Width,Screen.Height,D3DFMT_A8R8G8B8,
                                         D3DPOOL_SCRATCH,F3D3Surf9_SS,nil);

これは、スクリーンショットを取得してレンダリングするために使用するコードです

FDIrect3DDevice9.BeginScene;

FDirect3DDevice9.Clear(0,0,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,255),0,0);
FDirect3DDevice9.GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO, BackBuffer);

FDirect3DDevice9.GetFrontBufferData(0,F3D3Surf9_SS);  //Get the screen shot

FDirect3DDevice9.StretchRect(F3D3Surf9_SS,nil,BackBuffer,nil,D3DTEXF_NONE); //Draw it

FDIrect3DDevice9.EndScene;
FDirect3DDevice9.Present(nil,nil,0,nil);

ただし、これは機能しません。

画像は画面に描画されません。面 A または B を画面に描画すると、それは機能しますが、Surface SS では機能しません。ただし、Surface SS にスクリーンショットが含まれていることはわかっていD3DXSaveSurfaceToFileます。これは、ハードディスクに配置した結果のビットマップを呼び出すと、有効なスクリーン ショットになるためです。

これを行う適切な方法について何か考えはありますか?

4

1 に答える 1

3

これが機能しない理由は、F3D3Surf9_SSが D3DPOOL_SCRATCH によってシステム メモリで宣言されており、私が試みたようにバック バッファーに直接描画できないためです。

したがって、私の解決策は、F3D3Surf9_Aサーフェスを使用UpdateSurfaceして、システム メモリ内のスクリーンショットをビデオ メモリ内のサーフェス A にコピーすることでした。

これを機能させるために私がしなければならなかった他の唯一の変更は、スクリーンショット サーフェスと同じ形式でサーフェス A を作成することでした: D3DFMT_A8R8G8B8. また、UpdateSurface の宛先サーフェスがソース サーフェスよりも大きいことを確認する必要がありました。

ノート:

  • ビデオ メモリからシステム メモリに読み込んでからビデオ メモリに戻すため、これは低速です。
  • OS や他のアプリケーションが画面に表示するすべてのものをキャプチャしたいので、アプリケーションにこれが必要でしたが、自分のアプリケーションについて心配している場合は、より良い代替手段があります。
  • システム メモリに置かずに GetFrontBufferData を実行する方法を知っている場合 (それが機能していることが確認できる唯一の方法です)、教えてください。
于 2011-04-04T13:18:13.230 に答える