Llamando al API de WinRT desde aplicaciones de escritorio normales en C#

Rafael Ontivero

Programador sistemas embebidos

http://geeks.ms/blogs/rfog/

Microsoft MVP

LinkedIn: http://es.linkedin.com/pub/rafael-ontivero/54/622/8aa

¿Hay necesidad de ello?

Personalmente creo que sí, aunque no es válido para todas las situaciones. Supongamos por un momento que estamos haciendo una versión de escritorio clásico de nuestra aplicación. Supongamos también que dicha versión se ejecutará en Windows 8, tanto en un ordenador como en una tableta, ya sea de tipo x86/x64 (que no es más que un PC con forma de tableta) o de RT PRO. Y ahora suponed que queréis, por ejemplo, acceder al API de sensores que solo se encuentra disponible para las aplicaciones RT.

Quizás en este momento actual no sea muy necesario, pero podría existir la posibilidad de que, en un futuro, Microsoft implementara más cosas para la parte RT que no estén en la Win32…

Pero esperad un momento, que esto requiere algo más de explicación.

¿RT, Win32?

Hasta Windows 7 sólo había un Amo del Calabozo, que se llama Win32. Ese es el API de desarrollo nativo para Windows desde su primera versión. Cualquier programa, librería de terceros o lo que fuera, terminaba llamando a esas funciones. Incluso .NET. De hecho, .NET es una capa asentada sobre Win32, y de hecho, en cualquier momento se podía acceder a dicho API desde la mayoría de bibliotecas de terceros, incluso desde cosas tan exóticas como Visual Basic, Delphi, C++ Builder o QT.

Luego vino Windows RT y Windows 8 y Microsoft cambió las reglas del juego, pero sólo un poco. En principio ahora hay dos API diferentes, la de Win32 tradicional que sigue estando disponible para las aplicaciones de escritorio y sobre la que corre el .NET tradicional, y una nueva basada en componentes COM y escrita en C++/CX, sobre la que se asienta la parte .NET compatible con RT.

Es decir, y sólo en teoría y a efectos prácticos, ahora tenemos dos API para generar aplicaciones Windows:

  • Escritorio clásico: Win32 con .NET Framework y cualquier otra librería.
  • Escritorio moderno: C++/CX, .NET 4.5 for RT y un pequeño subconjunto de Win32.

El hecho de que la parte RT también esté basada en Win32 no nos interesa porque no podemos acceder a ella si queremos poner nuestra aplicación en la Tienda.

Por lo tanto, ahora tenemos dos juegos de funcionalidades para programar. Dependiendo del que elijamos, nuestra aplicación será:

  • De escritorio clásico que todos conocemos que funcionan en Windows 8 x86/x64 y RT PRO (que no deja de ser un x86/x64).

  • RT: Ocupan toda la pantalla y sólo se ejecutan en las tabletas puras o RT.

¿Dónde está la prohibición?

Para crear aplicaciones RT, tenemos el citado API C++/CX y .NET 4.5 para RT (que está encima del API anterior), y un pequeño subconjunto de funciones Win32. Y no podemos usar otra cosa.

Para crear aplicaciones de escritorio tenemos Win32 y .NET y cualquier otra cosa que hayamos estado usando hasta ahora. Pero, de forma oficial, no el API de RT.

¿Es un impedimento serio? No, claro que no, casi todo (por no decir todo), está disponible en Win32, pero podríamos querer usar algo de ese API, ya sea porque es más fácil y rápido de implementar que andar haciendo varias docenas de llamadas a funciones Win32 cuando en RT es utilizar una clase y tres métodos.

¿Nos lo impide alguien? Tampoco. No tenemos que pasar ningún tipo de certificación (como sí en RT), ni en general nadie nos va a exigir cuentas salvo los usuarios finales si nuestra aplicación es una porquería o se chupa la batería en un cuarto de hora. Por lo demás, somos libres de usar lo que queramos.

Por lo tanto, vamos a usar el API de RT en una aplicación Win32 pura.

¿Qué tengo que hacer?

En primer lugar, cierra Visual Studio y localiza el fichero .CSPROJ que guarda tu proyecto. Como es una cosa no documentada ni oficialmente sancionada por Microsoft, el IDE es incapaz de hacerlo.

Porque si intentamos añadir la referencia de Windows RT Core, vemos que no está:

Dn126142.7443E144117A36B24A4C6321A416236E(es-es,MSDN.10).png

Por lo tanto, una vez cerrado el IDE, abrimos el fichero citado y metemos la siguiente línea de texto:

<targetplatformversion>8.0</targetplatformversion>

¿Dónde? Pues en el primer <TargetGroup> que veamos, aquél en donde también aparece la línea:

Guardamos el fichero editado y volvemos a abrir Visual Studio. También podemos hacerlo mediante (Load/Unload Project) del menú contextual de Visual Studio sin necesidad de cerrar el IDE. Descargamos el proyecto, editamos el CSPROJ y lo volvemos a cargar.

Ahora sí, ahora sí que aparece la pestaña “Windows” de la store:

Dn126142.089269AC29B40F2C487F25FF8D891655(es-es,MSDN.10).png

Marcamos ese ensamblado y ya podemos editar los sensores en nuestro código:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
var light = LightSensor.GetDefault();
        if (light == null)
                return;

var minReportInterval = light.MinimumReportInterval;
var reportInterval = minReportInterval > 16 ? minReportInterval : 16;
light.ReportInterval = reportInterval;

light.ReadingChanged += (s, a) => Sensor.Dispatcher.BeginInvoke((Action)(() =>
{
Sensor.Text=String.Format("Luz: {0}", a.Reading.IlluminanceInLux);
 }));
}

Para completar el ejemplo, tenemos que añadir un control de texto dentro del Grid principal de nuestra aplicación:

<Grid>

<TextBlock Name="Sensor" VerticalAlignment="Center" HorizontalAlignment="Center" />

</Grid>

No obstante, si intentamos compilar ahora, nos dará un error diciéndonos que el evento no está soportado por el sistema. Simplemente nos falta añadir alguna referencia más: System.Runtime y System.Runtime.InteropServices.WindowsRuntime, que están en la carpeta C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETCore\v4.5.

Una vez añadidos, compilamos y ejecutamos sin problemas.

Fijaos que hemos tenido que hacer muchas cosas a mano. Lo más complicado es saber qué referencias tenemos que añadir, pero al final lo hemos conseguido. Lanzad la aplicación y subid o bajad las persianas de la habitación, o encended la luz y veréis cómo aparecen los cambios en el centro de la ventana… siempre y cuando tengáis un sensor de luz en vuestro equipo. En mi caso, funciona perfectamente en mi iMac con BootCamp.

¿Y si no quiero usar todo esto?

Pues fácil, tienes el equivalente de todo esto de forma nativa aquí: https://msdn.microsoft.com/en-us/library/windows/desktop/dd318953(v=vs.85).aspx. Dado que se tratan de varios interfaces COM puros y duros, quizás valga la pena hacerlo de la forma anterior, sobre todo si estás usando C#, VB:NET ó C++/CLI.

| Página de inicio |Artículos Técnicos | Comunidad