¿En qué escritorio funciona Metro?

Solo por curiosidad, desde el punto de vista del desarrollador de WinAPI, ¿en qué escritorio se ejecutan las aplicaciones de Metro?

Estas cosas:

introduzca la descripción de la imagen aquí

No sabía que sería un secreto … así que tuve que investigar un poco y esto es lo que encontré:

En primer lugar, para responder a mi pregunta original: las cosas de Metro (o Modern UI) se ejecutan exactamente en el mismo escritorio que las aplicaciones de “escritorio” (perdón por el juego de palabras). En realidad, todo es muy simple. La respuesta corta: todo lo aprobado por Microsoft se ejecuta en el contenedor Internet Explorer_Server (que, en términos simples, es Internet Explorer); o en el contenedor DirectUIHWND (que es la clase propietaria de Microsoft que representa su interfaz de usuario no documentada), todo en Windows con el estilo WS_EX_TOPMOST activado, lo que hace que se representen sobre el rest del contenido. ¡Y eso es todo!

Aquí hay un par de ejemplos:

Dividamos el escritorio y utilicemos Spy++ para ver qué sucede debajo del capó:

introduzca la descripción de la imagen aquí

Por lo tanto, si observamos la ventana de la aplicación “Weather”, no es más que la ventana normal (Win32) de la clase ” Internet Explorer_Server ” que se encuentra en la ventana de la clase ” Web Platform Embedding “, que a su vez se encuentra en el contenedor ” Windows.UI.Core.CoreWindow ” que tiene los estilos WS_EX_TOPMOST y WS_EX_NOREDIRECTIONBITMAP en:

introduzca la descripción de la imagen aquí

Si miras aún más a fondo, todo lo relacionado con Microsoft Metro se ejecuta desde el proceso WWAHOST.exe , que en términos simples es el contenedor para ejecutar JavaScript para las aplicaciones de Metro.

Ahora echemos un vistazo a la pantalla de inicio en sí. Ya que cubre completamente el escritorio, necesitamos usar una herramienta diferente y su capacidad de instantánea de tecla Shift para acceder a ella:

introduzca la descripción de la imagen aquí

De ella podemos obtener el manejador de la ventana de la pantalla de inicio (o 0x10158 en mi caso) y buscarlo en el Spy ++:

introduzca la descripción de la imagen aquí

Como puede ver en ambas herramientas, la pantalla de inicio tiene la clase de ventana DirectUIHWND , que se encuentra dentro de una ventana de la clase ImmersiveLauncher , que es la que tiene los estilos WS_EX_TOPMOST y WS_EX_NOREDIRECTIONBITMAP que lo hacen permanecer en la parte superior. Y esa es la única diferencia entre esta y cualquier otra ventana creada por una aplicación de “escritorio”.

Lo que también es interesante es cómo se representa el “escritorio” en caso de una situación de ventana dividida. Originalmente asumí que, en este caso, el escritorio simplemente se cambia (o se mueve) a un lado y se redimensiona, pero eso no es lo que sucede … En realidad (o en mi Windows 8.1) en caso de una división entre un escritorio y un escritorio. Aplicación de Metro, la aplicación de metro simplemente cubre el escritorio, pero el escritorio en sí no cambia su posición o tamaño. En ese caso, solo la barra de tareas y las ventanas de escritorio existentes se mueven y se redimensionan para ajustarse a la división. Esto podría ser ilustrado por este diagtwig:

introduzca la descripción de la imagen aquí

Como nota al margen, tal movimiento y cambio de tamaño pueden ser bastante molestos para un usuario, ya que las posiciones y tamaños originales de las ventanas del escritorio no se restauran cuando desaparece la división.

Y por último, un hallazgo algo inesperado. Decidí comprobar cómo los usuarios de Google podían implementar su navegador Chrome (que se ejecuta como una aplicación de Metro) y encontré esto:

introduzca la descripción de la imagen aquí

Chrome se representa en la ventana de clase Windows.UI.Core.CoreWindow , que pertenece al proceso propio de Google: ” C:\Program Files (x86)\Google\Chrome\Application\chrome.exe “. Por lo tanto, sin ir más lejos, evidentemente es posible encapsular una aplicación de estilo Metro en un contenedor que no sea de Microsoft, lo que es una buena noticia para los desarrolladores que no se preocupan por las aplicaciones XAML de AppStore 🙂

EDITAR: Olvidó mencionar, si planea mostrar su propio mensaje emergente desde un proceso de Win32 que está visible en la parte superior de una aplicación de Metro, debe hacer lo siguiente:

  • Establezca UIAccess="true" en el manifiesto del proceso. Puede hacerlo en Visual Studio yendo a Project Properties -> Linker -> Manifest Files y configure UAC Bypass UI Protection en YES. (Tenga en cuenta que puede mantener el UAC Execution Level como un asInvoker o no para requerir una elevación de su proceso).

  • Código de firma de su proceso. Es importante, ya que sin una firma no funcionará, y verá este mensaje de error: ” Se devolvió una referencia del servidor.

introduzca la descripción de la imagen aquí

Una alternativa a la firma (o para propósitos de prueba en su sistema de desarrollo) puede configurar la siguiente clave de registro en 0. (Sin embargo, no lo he intentado y no lo recomendaría debido a problemas de seguridad obvios. Pero parece que otra forma de probarlo si no está disponible un certificado de firma de código.)

 HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\ValidateAdminCodeSignatures 
  • Coloque el archivo ejecutable comstackdo en la %windir%\System32 , o de manera más realista en la %ProgramFiles%\Company\Product , o en la alternativa %ProgramFiles(X86)%\Company\Product para la ubicación de instalación de su producto.

También puede considerar leer el artículo de Raymond Chen sobre este tema.

  • Después de eso, cuando configure el estilo WS_EX_TOPMOST en su ventana emergente, se mostrará sobre cualquier otra ventana, incluidas las aplicaciones de Metro, la pantalla de inicio, etc.

Así que en otras palabras, haciendo esto:

 //You may also consider setting the WS_EX_NOACTIVATE style ::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0 , 0, 0, SWP_NOMOVE | SWP_NOSIZE); 

Puede lograr esto:

introduzca la descripción de la imagen aquí

Ya que dice que su problema real es saber si una aplicación de Metro se está ejecutando, la respuesta es llamar a IAppVisibility::GetAppVisibilityOnMonitor . Pasa el monitor que quieres comprobar. Tenga en cuenta que esto dará la respuesta correcta independientemente del escritorio en el que se ejecuten las aplicaciones.