Ayer, en el 27.º aniversario de Delphi, Embarcadero lanzó una demostración de WinUI 3 que presenté en el seminario web de aniversario. Aquí está el anuncio oficial junto con más información técnica. La demostración está disponible en GetIt.
Table of Contents
Introducción
El SDK de aplicaciones de Windows de Microsoft (anteriormente conocido como Project Reunion) incluye un nuevo marco de interfaz de usuario nativo llamado WinUI 3. WinUI 3 es el marco de interfaz de usuario actual en la arquitectura WinRT (Windows Runtime) y está disponible para aplicaciones empaquetadas (a través de contenedores APPX o MSIX) y aplicaciones GUI no empaquetadas (es decir, aplicaciones nativas regulares de Win32/Win64, como las creadas con Delphi y RAD Studio. Esta referencia a las aplicaciones empaquetadas no tiene nada que ver con los paquetes de Delphi.
Tenga en cuenta también que Windows App SDK es un conjunto diferente de herramientas del Windows SDK de nombre similar, disponible como parte de la instalación de Delphi durante mucho tiempo.
El proyecto de muestra SampleWinRT tiene como objetivo mostrar cómo construir una aplicación de GUI de Delphi simple puramente a partir del marco WinUI 3 (1.0) de Microsoft, lanzado en noviembre de 2021. Las versiones preliminares de WinUI3 requerían que la aplicación se implementara como una aplicación empaquetada de Windows. pero WinUI 3 (1.0) elimina esa restricción, lo que significa que puede crear una aplicación WinUI 3 en Delphi como una aplicación normal.
Puede encontrar más información sobre WinUI 3 aquí: https://docs.microsoft.com/en-us/windows/apps/winui/winui3
Puede encontrar más información sobre Windows App SDK aquí: https://docs.microsoft.com /es-es/windows/apps/windows-app-sdk/
La demostración viene con versiones actualizadas de las unidades de importación WinRT Delphi RTL, para admitir la versión 1.0 de WinUI 3. La versión actual de Delphi 11 Alexandria se envía con un conjunto anterior de las mismas unidades de importación.
Requisitos previos: instalador de Windows App Runtime y DLL de Windows App Runtime Loader
Para compilar e implementar una aplicación sin empaquetar, necesita un par de cosas, como se detalla en https://docs.microsoft.com/en-us/windows/apps/windows-app-sdk/deploy-unpackaged-apps
1. Primero, necesita el instalador del SDK de aplicaciones de Windows , que puede obtener desde un enlace de descarga en la página de Microsoft antes mencionada, o descargarlo desde https://aka.ms/windowsappsdk/1.0-stable/msix-installer. Esto le brinda el archivo de archivo redistribuible, actualmente llamado Microsoft.WindowsAppRuntime.Redist.1.0.0.zip, que contiene instaladores para las plataformas x86 y x64 (ambas llamadas WindowsAppRuntimeInstaller.exe) en carpetas con nombres sensatos.
Ejecutar el instalador (con privilegios elevados) garantizará que tenga instalado Windows App Runtime; se ubica en carpetas ocultas en C:Program FilesWindowsApps, por ejemplo, la versión x86 podría instalarse en C:Program FilesWindowsAppsMicrosoft.WindowsAppRuntime.1.0_0.319.455 .0_x86__8wekyb3d8bbwe.
2. Lo segundo que necesita es la DLL del cargador de Windows App Runtime , Microsoft.WindowsAppRuntime.Bootstrap.dll. Este archivo se obtiene del paquete NuGet del SDK de la aplicación de Windows, actualmente Microsoft.WindowsAppSDK.1.0.0.nupkg, que está disponible en https://www.nuget.org/packages/Microsoft.WindowsAppSDK en la carpeta runtimeswin10-x86native o tiempos de ejecuciónwin10-x64native. Esta DLL debe colocarse junto a su ejecutable para ubicarse al inicio de la aplicación cuando se llame a las API relevantes. La DLL del cargador (o DLL de arranque) es responsable de ubicar una versión adecuada de Windows App Runtime, que implementa WinUI 3, en función de los valores de versión pasados a su API de inicio.
Nota: si usó la compatibilidad con el componente TEdgeBrower de Delphi, que envuelve otra característica del SDK de la aplicación de Windows, es posible que observe una similitud en los requisitos para un tiempo de ejecución (que también necesitan los usuarios finales) y un SDK con una DLL cargada redistribuible
Descargando la Demostración
La demostración de Delphi WinUI 3 está disponible en GetIt para los clientes de RAD Studio 11 Alexandria. Al instalarlo, el código fuente de la demostración y de los archivos de biblioteca requeridos se instalan junto con un archivo Léame con contenido similar a esta publicación de blog. Este es el paquete GetIt:
Introducción a la demostración
La aplicación de demostración está construida como una aplicación de consola, no por necesidad, pero para que la información se pueda escribir en la ventana de la consola a medida que avanza la aplicación, ofreciendo también una forma de mostrar mensajes de error (como dependencias faltantes)
Nota: WinUI 3 requiere que ejecute el proceso sin privilegios elevados. Como tal, la demostración verifica esto y sale con un mensaje simple si encuentra privilegios elevados. Sin esta verificación en su lugar, WinUI 3 bloquea la aplicación de una manera aparentemente sin gracia.
Suponiendo que pasamos los privilegios, verifique que la aplicación llame a la API de inicialización en la DLL del cargador, MddBootstrapInitialize , y si eso ubica e inicia Windows App Runtime, la aplicación continúa con la inicialización. Antes de salir de la aplicación, llama a MddBootstrapShutdown para limpiar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
uses WinRT; const // From includeWindowsAppSDK-VersionInfo.h in WinAppSDK NuGet package WINDOWSAPPSDK_RELEASE_MAJORMINOR = $00010000; WINDOWSAPPSDK_RUNTIME_VERSION_UINT64 = $0000013F01C70000; WINDOWSAPPSDK_RUNTIME_VERSION_DOTQUADSTRING = '0.319.455.0'; var PackageVersion: PACKAGE_VERSION; ... PackageVersion.Version := WINDOWSAPPSDK_RUNTIME_VERSION_UINT64; var HR := MddBootstrapInitialize(WINDOWSAPPSDK_RELEASE_MAJORMINOR, nil, PackageVersion); if Succeeded(HR) <strong>then try Main; WriteLn('Press Enter (again) to continue'); Readln; finally MddBootstrapShutdown; |
Como puede ver, las versiones del paquete de tiempo de ejecución y lanzamiento del SDK se toman prestadas de un archivo de encabezado (.h) ubicado dentro del paquete NuGet del SDK de la aplicación de Windows
Dentro de Main llamamos al método de inicio estático del objeto de la aplicación WinUI 3; consulte https:// docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.application.start . Esto requiere una devolución de llamada que se ejecutará cuando la aplicación se inicialice, permitiéndonos configurar las cosas como deseamos. Afortunadamente, las devoluciones de llamada de WinRT (incluidas las devoluciones de llamada de WinUI 3) tienen la misma implementación que un método anónimo de Delphi, por lo que usamos un método anónimo para configurar el controlador de eventos OnLaunched de nuestra aplicación .
En WinUI 3 , OnLaunched no es en realidad un controlador de eventos. En cambio , OnLaunched , https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.application.onlaunched , es un método que se espera que anule en una clase que hereda de WinUI. clase de aplicación. ¿Cómo lidiamos con este requisito de heredar de una clase WinRT de Delphi?
WinUI nos ayuda proporcionando un mecanismo que podemos utilizar. En un caso como este, heredar de una clase WinUI 3 implica 3 objetos:
1) Un objeto interno que proporciona la implementación base, proporcionada por WinUI, en este caso, una implementación de aplicación base. Este objeto interno implementará una interfaz que define los métodos para los que proporcionaremos implementaciones; IApplicationOverrides en este caso.
2) Un objeto externo (a veces denominado objeto base) que proporciona la implementación personalizada de los métodos en cuestión. Este objeto externo, que proporcionaremos, también implementará IApplicationOverrides .
3) Un objeto contenedor, que combina el objeto interno y externo, y lo proporciona WinUI
Aquí está el código de Main :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
var AppInner: IInspectable; var AppOuter: IApplicationOverrides; var AppWrapper: IApplication; // In this code block we use an anonymous procedure (which Delphi implements as an // interface with an Invoke method) that matches the layout of the callback interface type TCallbackProc = reference to procedure (p: IApplicationInitializationCallbackParams) safecall; procedure Main; begin // Here we define an anonymous method and cast it to the matching WinUI interface type var CallbackProc: TCallbackProc := procedure (p: IApplicationInitializationCallbackParams) safecall begin // First we create our derived class AppOuter := TDerivedApp.Create as IApplicationOverrides; // Then we get the IApplicationFactory... var Factory := TApplication.Factory; // ... and use it to get an IApplication wrapper, AppWrapper, // and an IApplicationOverrides inner as well AppWrapper := Factory.CreateInstance(AppOuter, AppInner); // We store the inner object in the outer one so // we can call the base functionality when needed AppOuter.Inner := AppInner as IApplicationOverrides; end; var AppInitCallback := ApplicationInitializationCallback(CallbackProc); TApplication.Start(AppInitCallback); end; |
El código de personalización de la aplicación es de esta clase:
1 2 3 4 5 6 7 8 9 10 |
type TDerivedApp = class(TInspectableObject, IApplicationOverrides) private FInner: IApplicationOverrides; public // IApplicationOverrides methods procedure OnLaunched(args: ILaunchActivatedEventArgs); safecall; ... property Inner: IApplicationOverrides read FInner write FInner; end; |
El método OnLaunched entonces tiene la libertad de realizar toda la configuración de la aplicación requerida. En este caso, creamos y configuramos una ventana: https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.window y la completamos con algunos controles, creando la siguiente interfaz de usuario:
Busque en el código todos los detalles de lo que sucede, pero en resumen:
- Creamos un control StackPanel y lo colocamos en la ventana, luego se crea un botón con un controlador de eventos Click y se agrega al StackPanel .
- A continuación, usamos algo de XAML para crear otro StackPanel y un control secundario de botón, nuevamente con un controlador de eventos Click, agregando el StackPanel a la ventana. Eso nos da 2 enfoques para lograr el mismo objetivo.
- Finalmente, se usa un poco más de XAML para crear una cuadrícula y, dentro de ella, un TextBlock , que luego tiene un par de controladores de eventos agregados para OnPointerEntered y OnPointerExited .
- Finalmente, terminamos con una ventana que muestra un par de botones y un bloque de texto. Se puede hacer clic en los botones para cambiar su título y el bloque de texto cambia de color cuando mueve el mouse dentro y fuera de él.
Tenga en cuenta que para los controles de interfaz de usuario creados dinámicamente (como el primer botón), los controladores de eventos se pueden asociar directamente, mientras que cuando los controles se crean cargando una configuración XAML, el código debe ubicar el objeto coincidente para asociarle un controlador de eventos.
Nota: a diferencia de C# y C++, la proyección del lenguaje para Delphi actualmente no incorpora todas las diversas interfaces implementadas por los objetos WinRT y WinUI 3 en clases de proxy unificadas, por lo que hay mucho más trabajo de interfaz en marcha que en otros lugares.
Que sigue
Esta demostración del uso de Win UI 3 en una aplicación Delphi 11 empaquetada o no empaquetada está destinada principalmente a cualquier persona que quiera experimentar con esta nueva tecnología de interfaz de usuario desde el punto de vista de Delphi. Como Embarcadero, estamos siguiendo la evolución de WinUI 3 y planificando cómo admitirlo en el futuro. Microsoft ha anunciado soporte futuro para hospedar controles de WinUI 3 dentro de un identificador de formulario de Windows tradicional (es decir, una aplicación VCL o FMX) a través de las islas XAML para Win UI 3, una función que se espera para finales de 2022, por lo que es muy pronto para que hablemos un plan para una integración más fluida. Manténganse al tanto.
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition