2012-04-06 10 views
22

Necesito capturar la salida visual (como una captura de pantalla) de una ventana de DirectX. Actualmente, uso this approach.
Pero, cuando la ventana está en segundo plano, captura lo que está delante de ella.¿Captura la salida visual de una aplicación DirectX, incluso en segundo plano?

Veo que las ventanas DirectX se renderizan incluso cuando se minimizan o en segundo plano, por lo que esto debería ser posible.
Pero, ¿cómo? (También necesita ser rápido, y también debe funcionar en Windows XP, lamentablemente ...)

Editar: Estoy muy ocupado estos días ... No se preocupe, pondré el recompensa si expira.

+0

No sé si esto es aplicable a su proyecto, pero uno, teórico, solución que conozco es a cree un retraso en la función de captura de salida visual para que pueda volver a la ventana de DirectX antes de comenzar a grabar. – GeorgePotter

+0

No entiendo lo que quiere decir ... – Vercas

+0

Usted dice que desea capturar lo que se representa con la ventana de DirectX, incluso si dicha ventana está en segundo plano. Si la razón por la que desea hacerlo es porque, por ejemplo, hay un retraso entre el inicio del programa de grabación y el cambio a la ventana de DirectX, entonces podría intentar crear un retraso en el programa para permitirle cambiar a la ventana de DirectX. Probablemente esa no sea su situación pero, si lo es, ese método podría ayudar. – GeorgePotter

Respuesta

5

Google rápido y encontré este proyecto de código que se relaciona con Windows XP. No sé si puedes aplicar este conocimiento a Windows Vista y 7 ??

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

EDIT:

He encontrado este artículo así:

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

Esto enlaza fuera de Justins entrada de blog aquí desde los comentarios. Parece que estaba trabajando en esto con alguien (veo que ese es tu enlace).

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

+0

¿No mencioné C#? Además, parece mirar el "buffer frontal", que es toda la pantalla. Necesito el buffer de la aplicación explícitamente. – Vercas

+0

Disculpas, no vi eso. Mmmmmnnnn estoy tratando de pensar qué haría en XNA (sé que esto no es DirectX) y pienso en una solución. Déjame pensar. – garfbradaz

+0

Uh, déjame expirar esto. El artículo de Code Project que me vinculó no funciona con Windows DirectX. Algunos no aparecen en absoluto, algunos aparecen grises. Si recuerdo bien, las ventanas sin estilo de borde tampoco funcionan. Ahora, la captura de pantalla con el artículo de Direct3D implica engancharse en la aplicación. El problema es que la mayoría de las aplicaciones de DirectX son juegos, y la mayoría de los juegos están protegidos por cosas como VAC y Game Guard, lo que matará el proceso del juego al instante y me dará una advertencia o una prohibición permanente inmediata. – Vercas

1

El código que se ha vinculado a (de spazzarama), que le dijo que estaba utilizando en su proyecto, captura el búfer frontal de su dispositivo DirectX. ¿Has intentado capturar el búfer posterior en su lugar? Yendo desde el código en su sitio vinculado, cambiaría la línea 90 desde

dispositivo.GetFrontBufferData (0, superficie);

a

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

Esto también implicaría eliminar las líneas 96-98 en su ejemplo vinculado. El backbuffer podría generarse sin la ventana obstructiva.

EDITAR

importa todo eso. Me acabo de dar cuenta de que su código de ejemplo vinculado está usando el identificador de ventana para definir una región de la pantalla y no está haciendo nada con la ventana de DirectX. Su código de muestra no funcionará alrededor de la obstrucción porque su región ya está dibujada con la otra ventana en frente de la misma cuando accede a ella.

Su mejor apuesta para salvar la aplicación es, probablemente, llevar la ventana de DirectX a la parte superior de la pantalla antes de ejecutar el código para capturar la imagen. Puede usar la función Wind32API BringWindowToTop para hacer eso (http://msdn.microsoft.com/en-us/library/ms632673%28VS.85%29.aspx).

+0

Ya estoy usando * SetForegroundWindow * para esto, pero requiere una comunicación compleja entre procesos para garantizar que dos programas no salten al frente al mismo tiempo ... Es muy ineficiente y atasca mi aplicación. – Vercas

19

Para capturar ventanas Direct3D que se encuentran en el fondo (o se transportan fuera de la pantalla), creo que usted tiene las siguientes opciones:

  1. Inyectar y el gancho Direct3D dentro de la aplicación de destino a través del enlace que ya ha publicado or this more up-to-date example (EasyHook puede ser difícil de configurar pero funciona muy bien): siempre puede pedir ayuda para que funcione. He utilizado esa técnica para capturar en una serie de juegos sin problemas (más recientemente para un proyecto de ambilight-clone). El problema con este enfoque es su preocupación por la prohibición de juegos que causa prohibiciones, sin embargo, FRAP también utiliza el enganche para lograr esto, por lo que quizás sus preocupaciones sean exageradas. Creo que los jugadores que están prohibidos para una captura de pantalla es una forma costosa de averiguarlo.

  2. Para aplicaciones con ventana en Vista/Win 7: puede inyectar y enganchar el DWM y realizar sus solicitudes de captura a través de su superficie compartida. He tenido este working on Vista, pero no he terminado de hacerlo funcionar en Windows 7, he aquí un ejemplo de que funciona para Windows 7 http://www.youtube.com/watch?v=G75WKeXqXkc. El principal problema con este enfoque es el uso de API indocumentadas, lo que podría significar que su aplicación se interrumpe sin previo aviso en un lanzamiento de parche de Windows; también tendría que volver a aplicar la técnica para cada nuevo sabor principal de Windows. Esto tampoco aborda su necesidad de capturar en Windows XP.

  3. También dentro de DWM, hay una API en miniatura. Esto tiene limitaciones dependiendo de lo que trates de hacer. Hay información sobre esta API junto con otras API de DWM aquí http://blogs.msdn.com/b/greg_schechter/archive/2006/09/14/753605.aspx

  4. Existen otras técnicas para interceptar las llamadas de Direct3D sin utilizar EasyHook, como la sustitución de varias DLL con envoltorios. Va a encontrar varias otras técnicas de juego de enganche/interceptación aquí: http://www.gamedeception.net/

  5. Simplemente lleve la aplicación Direct3D al primer plano (que supongo que es indeseable en su situación) - esto no funcionaría para las ventanas fuera de la pantalla a menos que también mover la ventana

  6. Desafortunadamente, la única solución para Windows XP que se me ocurre es interceptar Direct3D API de alguna forma.

Solo una aclaración sobre la representación de Direct3D mientras se minimiza. Durante mis pruebas bastante limitadas sobre este asunto, he encontrado que esto depende de la aplicación; generalmente es not recommended que la representación se lleva a cabo mientras la aplicación está minimizada (también este reference), sin embargo, continúa apareciendo en segundo plano.

ACTUALIZADO: proporcionado enlace adicional al ejemplo más de la inyección hasta a la fecha para el punto 1.

+0

Me olvidé de mencionar que EasyHook también proporciona compatibilidad con kernel/nivel de controlador para enganchar. Supongo que esto es similar a cómo personas como PLAYXPERT tienen su sistema de superposición de juegos funcionando. –

+0

Investigué un poco y descubrí que la mayoría de los protectores de juegos usan controladores para monitorear los juegos ... No hay forma de que pueda inyectar código de manera segura en un proceso sin una "licencia de desarrollador" del (de los) protector (es) del juego. Debe haber otra forma ... ¿Cómo demonios hace DWM obtener las miniaturas en primer lugar? – Vercas

+0

Creo que DWM usa superficies compartidas y DXGI, una buena descripción de esto está aquí: http://msdn.microsoft.com/en-us/library/windows/desktop/ee913554(v=vs.85).aspx No creo que sea posible iniciar una superficie compartida sin antes tener una referencia al dispositivo, por lo que aún necesita algo en la aplicación de destino. –

Cuestiones relacionadas