web-dev-qa-db-ja.com

DirectXアプリケーションのビジュアル出力をキャプチャします-バックグラウンドでも?

DirectXウィンドウのビジュアル出力(スクリーンショットなど)をキャプチャする必要があります。現在、私は このアプローチ を使用しています。
ただし、ウィンドウがバックグラウンドにある場合は、ウィンドウの前にあるものはすべてキャプチャされます。

DirectXウィンドウは、最小化またはバックグラウンドでもレンダリングされるので、これは可能であるはずです。
しかし、どうやって? (また、高速である必要があり、Windowsで動作する必要がありますXP、残念ながら...)

編集:最近はとても忙しいです...心配しないでください。期限が切れたらバウンティを元に戻します。

23
Vercas

バックグラウンドにある(または画面から移動した)Direct3Dウィンドウをキャプチャするには、次のオプションがあると思います。

  1. すでに投稿したリンクを介してターゲットアプリケーション内にDirect3Dを挿入してフックします またはこの最新の例 (EasyHookはセットアップが難しい場合がありますが、非常にうまく機能します)-いつでも可能ですそれを機能させるための助けを求めてください。私はそのテクニックを使用して、問題なく多くのゲームでキャプチャしました(最近では、ambilight-cloneプロジェクトで)。このアプローチの問題は、禁止を引き起こすゲーム保護についての懸念ですが、FRAPもこれを達成するためにフッキングを使用しているため、おそらく懸念は誇張されていますか?スクリーンショットで禁止されているゲーマーは、それを見つけるための費用のかかる方法だと思います。

  2. Vista/Win 7のウィンドウアプリケーションの場合、DWMを挿入してフックし、共有サーフェスを介してキャプチャ要求を行うことができます。私はこれを持っています Vistaで動作しています 、しかしそれをWindows 7で動作させるのを終えていません、これはWindows 7で動作する例です http://www.youtube.com/ watch?v = G75WKeXqXkc 。このアプローチの主な問題は、文書化されていないAPIの使用です。これは、Windowsパッチのリリース時に警告なしにアプリケーションが破損する可能性があることを意味します。また、新しい主要なWindowsフレーバーごとにテクニックをやり直す必要があります。これは、WindowsXPでキャプチャする必要性にも対応していません。

  3. また、DWM内には、サムネイルAPIがあります。これには、何をしようとしているかによって制限があります。このAPIと他のDWMAPIに関する情報がここにあります http://blogs.msdn.com/b/greg_schechter/archive/2006/09/14/753605.aspx

  4. EasyHookを使用せずにDirect3D呼び出しをインターセプトする方法は他にもあります。たとえば、さまざまなDLLをラッパーに置き換えるなどです。ここには、他のさまざまなゲームのフック/インターセプトテクニックがあります: http://www.gamedeception.net/

  5. Direct3Dアプリケーションをフォアグラウンドに移動するだけです(これはあなたの状況では望ましくないと思います)。これは、ウィンドウも移動しない限り、画面外のウィンドウでは機能しません。

  6. 残念ながら、私が考えることができるWindows XPの唯一の解決策は、何らかの形でDirect3DAPIを傍受することです。

最小化された状態でのDirect3Dレンダリングの説明。この問題に関するかなり限られたテスト中に、これはアプリケーションに依存することがわかりました。通常、アプリケーションが最小化されている間にレンダリングが行われるのは 非推奨 です(これも 参照 )が、バックグラウンドにある間はレンダリングを継続します。

[〜#〜]更新[〜#〜]:ポイント1のより最新の注入例への追加リンクを提供しました。

22
Justin Stenning

簡単なグーグルと私はWindowsXPに関連するこのコードプロジェクトを見つけました。この知識をWindowsVistaと7に適用できるかどうかわかりませんか?

http://www.codeproject.com/Articles/5051/Various-methods-for-capturing-the-screen

編集:

私もこの記事を見つけました:

http://www.codeproject.com/Articles/20651/Capturing-Minimized-Window-A-Kid-s-Trick

これは、コメントからここにあるジャスティンのブログ投稿からリンクしています。彼は誰かとこれに取り組んでいたようです(私はあなたのリンクについてです)。

http://spazzarama.com/2009/02/07/screencapture-with-direct3d/

5
garfbradaz

プロジェクトで使用していると言った(spazzaramaからの)リンクしたコードは、DirectXデバイスのフロントバッファーをキャプチャします。代わりにバックバッファをキャプチャしてみましたか?リンク先サイトのコードから、90行目を次のように変更します。

device.GetFrontBufferData(0, surface);

Surface backbuffer = device.GetBackBuffer(0, 0, BackBufferType.Mono);
SurfaceLoader.Save("Screenshot.bmp", ImageFileFormat.Bmp, backbuffer);

これには、リンクされた例の行96〜98を削除することも含まれます。バックバッファは、ウィンドウを妨げることなく生成される可能性があります。

[〜#〜]編集[〜#〜]

そのすべてを気にしないでください。リンクされたサンプルコードがウィンドウハンドルを使用して画面の領域を定義しており、DirectXウィンドウでは実際には何もしていないことに気づきました。サンプルコードは、アクセスするまでに他のウィンドウが前面に表示されているため、障害物を回避できません。

アプリケーションを救済するための最善の策は、コードを実行して画像をキャプチャする前に、DirectXウィンドウを画面の上部に表示することです。 Wind32APIBringWindowToTop関数を使用してこれを行うことができます( http://msdn.Microsoft.com/en-us/library/ms632673%28VS.85%29.aspx )。

1
Jim