17

これは私を困惑させます。DirectXはすべてをバイパスし、デバイスドライバーと直接通信するため、GDIやその他の通常の方法は機能しません。Aeroが無効(または使用不可)でない限り、表示されるのは画面の左上にある黒い長方形だけです。DirectXを使用してバックバッファーを取得して保存し、他のフォーラムで提案されていることを試しましたが、同じ結果が得られます。

デバイス->GetFrontBufferData(0、サーフェス); D3DXSaveSurfaceToFile( "fileName"、D3DXIFF_BMP、surface、NULL、NULL);

Aeroが有効になっているときに別のフルスクリーンDirectXアプリケーションのスクリーンショットを取得する方法はありますか?

4

7 に答える 7

23

迂回路をご覧ください。

Detoursを使用するとDirect3DCreate9、のような呼び出しを計測できます。この呼び出しでは、セットアップに必要な操作を実行してから、フレームキャプチャを実行します。IDirect3D9::CreateDeviceIDirect3D9::Present

于 2009-12-26T00:03:55.330 に答える
9

これは、 DLLインジェクションを介してIDirect3DDevice9オブジェクトをフックし、EasyHook(Microsoft Detoursなど)を使用して関数をフックするC#の例です。これは、FRAPSの動作と似ています。

これにより、ウィンドウ/フルスクリーンモードで画面をキャプチャでき、フロントバッファからデータを取得するよりもはるかに高速なバックバッファを使用できます。

小さなC++ヘルパーDLLを使用して、実行時にフックするIDirect3DDevice9オブジェクトのメソッドを決定します。

更新: DirectX 10/11については、D3D 9、10、および11のスクリーンキャプチャとオーバーレイを参照してください。

于 2010-05-15T02:02:18.420 に答える
3

これは私が今テストとして使用したコードのスニペットであり、機能しているようです。

幅と高さは、ウィンドウではなくウィンドウモードの画面のサイズです。したがって、私にとっては、それらは1280 x 1024に設定されており、レンダリングしているウィンドウのサイズではありません。

mEngine-> getDevice()を、IDirect3DDevice9を取得する何らかの方法に置き換える必要があります。このコードをランダムなd3dアプリに挿入したところ、テストが簡単になりました。ただし、そのアプリからの出力と、同時に実行されている別のd3dアプリの両方をキャプチャすることは確認できます。

ああ、あなたが言わなかったように、これはD3D9だと思いました。d3d10または11についてはよくわかりません。

IDirect3DSurface9* surface;
mEngine->getDevice()->CreateOffscreenPlainSurface(width, height, D3DFMT_A8R8G8B8,     D3DPOOL_SCRATCH, &surface, NULL);
mEngine->getDevice()->GetFrontBufferData(0, surface);
D3DXSaveSurfaceToFile("c:\\tmp\\output.jpg", D3DXIFF_JPG, surface, NULL, NULL);
surface->Release();
于 2009-12-26T14:54:18.563 に答える
2

fraps:taksiのようなオープンソースプログラムがありますが、時代遅れに見えます

于 2009-12-26T13:23:18.277 に答える
2

ここでは、Frapsがどのように機能するかについて説明します。簡単ではありません。

http://www.woodmann.com/forum/archive/index.php/t-11023.html

別のDirectXデバイスからフロントバッファを読み取ろうとするトリックは、初期化されていないメモリの運が原因でたまにしか機能しない可能性があります。

于 2009-12-29T07:05:23.103 に答える
2

J99の回答に従って、ウィンドウモードとフルスクリーンモードの両方でコードを機能させました。これはD3D9でも行われます。

  IDirect3DSurface9* surface;
  D3DDISPLAYMODE mode;
  pDev->GetDisplayMode(0, &mode); // pDev is my *IDirect3DDevice
  // we can capture only the entire screen,
  // so width and height must match current display mode
  pDev->CreateOffscreenPlainSurface(mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &surface, NULL);
  if(pDev->GetFrontBufferData(0, surface)==D3D_OK)
  {
    if(bWindowed) // a global config variable
    {
      // get client area in desktop coordinates
      // this might need to be changed to support multiple screens
      RECT r;
      GetClientRect(hWnd, &r); // hWnd is our window handle
      POINT p = {0, 0};
      ClientToScreen(hWnd, &p);
      SetRect(&r, p.x, p.y, p.x+r.right, p.y+r.bottom);
      D3DXSaveSurfaceToFile(szFilename, D3DXIFF_JPG, surface, NULL, &r);
    }
    else
      D3DXSaveSurfaceToFile(szFilename, D3DXIFF_JPG, surface, NULL, NULL);
  }
  surface->Release();

CreateOffscreenPlainSurfaceのフォーマットとプールのパラメーターは完全に同じでなければならないようです。

于 2012-10-02T11:33:01.107 に答える
1

私のInvestigoプロジェクトをご覧になることをお勧めします。

DirectXプロキシDLLを使用して、DirectXAPI関数をインターセプトします。

Presentの呼び出し中にスクリーンショットを撮るためのコードがすでにそこにあります。UIからはまだアクセスできませんが。ただし、コードを簡単に有効にできるはずです。

http://www.codeproject.com/Articles/448756/Introducing-Investigo-Using-a-Proxy-DLL-and-embedd

于 2012-11-10T08:04:11.627 に答える