Kori 2월 17일, 2022에 포스트됨 공유하기 2월 17일, 2022에 포스트됨 Marco Cantu가 2022년 2월 15일에 기고한 Delphi WinUI 3 Demo를 번역한 글 Yesterday, on Delphi’s 27th anniversary Embarcadero released a WinUI 3 demo that I presented in the anniversary webinar. Here is the official announcement along with some more technical information. The demo is available in GetIt. 어제, 델파이 27주년 기념일을 맞아 나는 엠바카데로에서 WinUI 3 데모를 발표했다. 이 글은 WinUI 3 데모에 대한 공식 발표이며 세미나에서 다루어진 내용보다 더 많은 관련 기술 정보를 담고있다. 이 데모는 겟잇(GetIt)에서 받을 수 있다. 소개 (Introduction) Microsoft’s Windows App SDK (previously known as Project Reunion) includes a new native UI framework called WinUI 3. WinUI 3 is the current UI framework in the WinRT (Windows Runtime) architecture and it is available for packaged applications (via APPX or MSIX containers) and non-packaged GUI applications (that is regular Win32/Win64 native applications, like those created with Delphi and RAD Studio. This reference to packaged applications has nothing to do with Delphi packages. 마이크로소프트의 윈도우 앱 SDK (Windows App SDK - 구. Project Reunion)에는 WinUI 3이라는 새 네이티브 UI가 들어있다. WinUI 3은 현재 WinRT (윈도우 런타임) 아키텍처 안에 구현되어서 사용되고 있는 UI 프레임워크이다. WinUI 3는 (APPX 또는 MSIX 컨테이너를 통하는) 패키징되는 애플리케이션과 (일반 Win32/Win64 네이티브 애플리케이션처럼) 패키징되지 않는 GUI 애플리케이션을 모두 만들 수 있다. 델파이와 RAD스튜디오에서 만드는 것과 마찬가지이다. 하지만 패키징되는 애플리케이션과 우리가 사용하는 델파이 패키지와는 아무 관계가 없으니 혼동하지 않기 바란다. Keep also in mind that the Windows App SDK is a different set of tools from the similarly named Windows SDK, available as part of the Delphi installation for a long time. The sample project SampleWinRT is intended to show how to construct a simple Delphi GUI application purely out of Microsoft’s WinUI 3 (1.0) framework, released in November 2021. Pre-release versions of WinUI3 required the application to be deployed as a Windows packaged application, but WinUI 3 (1.0) removes that restriction meaning that you can build a WinUI 3 app in Delphi as a regular app. 이름이 비슷하긴 하지만, 윈도우 앱 SDK(Window App SDK)는 델파이가 설치될 때 오래전부터 함께 들어가던 윈도우 SDK(Windows SDK)와는 다른 것이다. 간단한 샘플 프로젝트인 이 SampleWinRT를 보면, 마이크로소프트에서 2021년 11월에 출시한 WinUI 3 (1.0) 프레임워크만 가지고 델파이 GUI 애플리케이션을 만드는 방법을 파악할 수 있다. WinUI3은 공식 출시 전까지만 해도 패키징된 윈도우 애플리케이션으로만 배포할 수 있다는 제한이 있었지만, WinUI 3 (1.0)이 발표되면서 이 제한은 사라졌다. 따라서 델파이에서는 일반 앱을 만든 것과 같은 방식으로 WinUI 3앱도 만들 수 있다. WinUI 3에 대한 자세한 내용: https://docs.microsoft.com/en-us/windows/apps/winui/winui3 윈도우 앱 SDK에 대한 자세한 내용: https://docs.microsoft.com/en-us/windows/apps/windows-app-sdk/ The demo comes with updated versions of the WinRT Delphi RTL import units, to support the 1.0 release of WinUI 3. The current Delphi 11 Alexandria version ships with an older set of the same import units. WinUI 3 1.0 버전을 지원하기 위해 이 데모에는 WinRT Delphi RTL 임포트 유닛(들)의 업데이트된 버전(들)이 함께 들어있다. 현재 델파이 11 알렉산드리아 버전에 있는 해당 유닛(들)은 예전 버전(들)이다. 전제 조건: 윈도우 앱 런타임 설치 프로그램 및 윈도우 앱 런타임 로더 DLL (Prerequisites: Windows App runtime installer and Windows App Runtime Loader DLL) In order to build and deploy an unpackaged app you need a couple of things 패키징되지 않은 앱을 빌드/배포 하려면 몇가지 준비가 필요하다. 자세한 내용: https://docs.microsoft.com/en-us/windows/apps/windows-app-sdk/deploy-unpackaged-apps 1. First, you need the Windows App SDK installer, which you can get from a download link on the aforementioned Microsoft page, or pull it down from https://aka.ms/windowsappsdk/1.0-stable/msix-installer. This gives you the redistributable file archive, currently called Microsoft.WindowsAppRuntime.Redist.1.0.0.zip, which contains installers for x86 and x64 platforms (both called WindowsAppRuntimeInstaller.exe) in sensibly named folders. 1. 첫째, 윈도우 앱 SDK 설치 프로그램이 필요하다. 다운로드 링크는 위에서 언급된 마이크로소프트 페이지에 있다. https://aka.ms/windowsappsdk/1.0-stable/msix-installer에서 받을 수도 있다. 재배포할 수 있는 파일들이 담긴 Microsoft.WindowsAppRuntime.Redist.1.0.0.zip 파일을 다운로드 하게 되는데, 설치 프로그램은 x86과 x64 등 각 플랫폼이 명시된 폴더에 들어있다. 설치파일의 이름은 WindowsAppRuntimeInstaller.exe으로 동일하다. Running the installer (with elevated privileges) will ensure that you have the Windows App Runtime installed – it goes into hidden folders under C:Program FilesWindowsApps, for example the x86 version might be installed within C:Program FilesWindowsAppsMicrosoft.WindowsAppRuntime.1.0_0.319.455.0_x86__8wekyb3d8bbwe. (상승된 윈도우 권한으로) 설치 프로그램을 실행해야 윈도우 앱 런타임이 잘 설치된다. 설치가 완료되면 윈도우 프로그램 폴더에 있는 WindowsApps 폴더 아래에 숨겨진 폴더가 생긴다. 예를 들어 x86 버전이라면 C:Program Files\WindowsApps\Microsoft.WindowsAppRuntime.1.0_0.319.455.0_x86__8wekyb3d8bbwe 폴더가 생긴다. 2. The second thing you need is the Windows App Runtime loader DLL, Microsoft.WindowsAppRuntime.Bootstrap.dll. This file is obtained from within the Windows App SDK NuGet package, currently Microsoft.WindowsAppSDK.1.0.0.nupkg, which is available from https://www.nuget.org/packages/Microsoft.WindowsAppSDK in the folder runtimeswin10-x86native or runtimeswin10-x64native. This DLL should be placed alongside your executable in order to be located at application startup when the relevant APIs are called. The loader DLL (or bootstrap DLL) is responsible for locating a suitable version of the Windows App Runtime, which implements WinUI 3, based on the version values passed into its startup API. 2.둘째, 윈도우 앱 런타임 로더 DLL인 Microsoft.WindowsAppRuntime.Bootstrap.dll이 필요하다. 이 파일은 윈도우 앱 SDK NuGet 패키지 (현재 이름은 Microsoft.WindowsAppSDK.1.0.0.nupkg) 안에 있다. 이 DLL을 받으려면 https://www.nuget.org/packages/Microsoft.WindowsAppSDK로 가서, Nuget 패키지 안에 있는 runtimes 폴더를 열고 win10-x86native 또는 win10-x64native 폴더를 열면 그 안에 있다 (역자 주: 위 1 단계에서 설치 프로그램을 실행하면 생기는 폴더 안에서도 찾을 수 있었다). 이 dll은 당신이 만든 실행파일과 같은 위치에 배포해야 한다. 그 이유는 애플리케이션이 시작되면서 해당 API(들)이 호출될 때 이 DLL을 찾을 수 있어야 하기 때문이다. 이 DLL (즉 부트스트랩 DLL)은 WinUI 3을 구현하는 윈도우 앱 런타임의 알맞은 버전을 찾는 역할을 하는데, 시작 API에 전달된 버전 값을 기반으로 찾는다. Note: If you used Delphi’s TEdgeBrower component support, which wraps another Window App SDK feature, you might notice a similarity in the requirements for a runtime (also needed by end users) and an SDK with a redistributable loaded DLL 참고: 만약 델파이 TEdgeBrower 컴포넌트를 사용한 경험이 있다면, 위 전제 조건이 비슷하다고 느낄 것이다. TEdgeBrower 컴포넌트 역시 윈도우 앱 SDK(Window App SDK) 기능을 에워싼 것이기 때문에, (최종 사용자에게도 요구되는) 런타임과 재배포가 허용되는 관련 DLL이 로드될 수 있어야 하고 해당 SDK가 필요하다. 데모 다운로드하기 (Downloading the Demo) The Delphi WinUI 3 demo is available on GetIt for RAD Studio 11 Alexandria customers. By installing it, the source code of the demo and of the required library files is installed along with a readme file with content similar to this blog post. This is the GetIt Package: 델파이 WinUI 3 데모는 RAD 스튜디오 알렉산드리아 사용자가 겟잇(GetIt)에서 받아서 설치할 수 있다. 데모의 소스 코드 그리고 요구되는 라이브러리 파일(들)의 소스 코드가 모두 설치된다. 이 글과 유사한 내용이 담긴 readme 파일도 함께 제공된다. 다음 그림과 같이 겟잇 패키지를 설치한다. 데모 소개 (Introducing to the Demo) The demo application is built as a console app, not out of necessity, but so information can be written to the console window as the application progresses, offering also a way to display error messages (such as missing dependencies) 데모 애플리케이션은 콘솔 앱으로 빌드된다. 굳이 콘솔 앱일 필요는 없지만, 콘솔 창에 애플리케이션의 진행 상황 정보가 씌어질 수 있고, (의존 빠짐 등의) 에러 메시지도 표시될 수 있기 때문에 그렇게 했다. Note: WinUI 3 requires you to run the process without elevated privileges. As such, the demo checks this and exits with a simple message if it finds elevated privileges. Without this check in place, WinUI 3 crashes the application in a seemingly graceless manner. 참고: WinUI 3 프로세스는 상승된 권한이 없이 실행되어야 한다. 그렇기 때문에, 이 데모는 상승된 권한으로 실행되고 있는 지를 검사하고 만약 그렇다면 간단한 메시지를 남기고 종료한다. 이 검사가 없다면, WinUI 3이 해당 애플리케이션을 우아하지 않게 깨버릴 것이다. Assuming we pass the privileges check the app calls the initialization API in the loader DLL, MddBootstrapInitialize, and if that locates and starts up the Windows App Runtime the application then proceeds with further initialization. Before exiting the app calls MddBootstrapShutdown to clean up: 권한 검사를 통과하고 나면, 이 앱의 MddBootstrapInitialize 메소드에서 윈도우 앱 런타임 로더 DLL 안에 있는 시작 API를 호출한다. 이 로더가 윈도우 앱 런타입을 잘 찾아서 시작시키고 나면, 이 앱에 구현된 추가 초기화를 진행한다. 앱이 종료하기 전에는 MddBootstrapShutdown 메소드가 호출되어 깨끗하게 모두 정리한다. uses WinRT; const // WinAppSDK NuGet 패키지 안에 있는 include 폴더 안에는 // WindowsAppSDK-VersionInfo.h 파일이 있는데 여기에 적힌 윈도우 앱 SDK 버전 정보를 사용한다. 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; As you can see, the SDK release and runtime package versions are borrowed from a header (.h) file located within the Windows App SDK NuGet package Within Main we call the static Start method of the WinUI 3 Application object – see https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.application.start. This takes a callback that will be run when the application initializes, allowing us to set things up as we wish. Fortuitously, WinRT callbacks (including WinUI 3 callbacks) have the same implementation as a Delphi anonymous method so we use an anonymous method to set up our application’s OnLaunched event handler. 위 코드와 같이, 윈도우 앱 SDK(Window App SDK)의 버전과 런타임 패키지 버전는 Windows App SDK NuGet 패키지 안에 있는 헤더 파일 (.h)에 있는 값을 가져다 쓴다. Main 프로시저에서는 WinUI 3 Application 오브젝트가 가지는 정적 메소드인 Start를 호출한다. 참고: https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.application.start. 이 Start 메소드는 애플리케이션 시작 절차를 진행할 때 콜백을 받기 때문에 이것을 사용하여 우리는 원하는 것을 설정할 수 있다. 우연하게도, (WinUI 3 콜백 등) WinRT의 콜백 구현은 델파이의 익명 메소드 구현과 같다. 따라서 우리는 익명 메소드를 사용하여 애플리케이션의 OnLaunched 이벤트 핸들러를 설정할 수 있다. In WinUI 3 OnLaunched is not actually an event handler. Instead OnLaunched – https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.application.onlaunched – is a method that we are expected to override in a class that inherits from the WinUI Application class. How do we cope with this requirement to inherit from a WinRT class from Delphi? WinUI 3의 OnLaunched는 실제로 이벤트 핸들러가 아니다. OnLaunched (https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.application.onlaunched)는 WinUI Application 클래스를 상속받는 클래스에서 재정의(Override) 하도록 되어 있는 메소드이다. WinRT 클래스를 상속받기 위해서는 이 요구사항을 대처해야 한다. 그렇다면 델파이에서는 어떻게 할까? WinUI helps us out by supplying a mechanism that we can make use of. In a case like this, inheriting from a WinUI 3 class involves 3 objects: WinUI에는 우리가 활용할 수 있도록 돕는 매커니즘이 있다. 이 데모처럼 WinUI 3 클래스를 상속받을 때는 오브젝트 3개가 필요하다. 1) An inner object that gives the base implementation, which is provided by WinUI, in this case a base Application implementation. This inner object will implement an interface that defines the method(s) we will be providing implementations for; IApplicationOverrides in this case. 1) WinUI가 제공하는 기반 구현을 제공하는 내부 오브젝트: 이 데모에서는 WinUI Application 오브젝트의 기반 구현이다. 이 내부 오브젝트는 구현을 제공할 메소드(들)을 정의하는 인터페이스를 구현한다. 이 데모에서는 IApplicationOverrides가 해당된다. 2) An outer object (sometimes referred to as a base object) that provides the custom implementation of the method(s) in question. This outer object, which we will provide, will also implement IApplicationOverrides. 2) 외부 오브젝트 (기반 오브젝트라고 부르기도 한다): 해당 메소드(들)의 사용자 정의를 구현한다. 이 바깥쪽 오브젝트는 우리가 제공하는데, 이 오브젝트에서도 IApplicationOverrides를 구현한다. 3) A wrapper object, which combines the inner and outer object, and is provided by WinUI 3) 에워싸는 래퍼 오브젝트: 안쪽 오브젝트와 바깥쪽 오브젝트를 묶는 오브젝트이며, WinUI에서 제공한다. Main 프로시저의 코드는 다음과 같다. var AppInner: IInspectable; var AppOuter: IApplicationOverrides; var AppWrapper: IApplication; //이 코드에서 우리는 (Invoke 메소드를 가지는 인터페이스 역할을 하는 델파이 구현으로) 익명 프로시저를 사용한다. // 이 익명 메소드는 구현하는 콜백 인터페이스와 틀이 일치해야 한다. type TCallbackProc = reference to procedure (p: IApplicationInitializationCallbackParams) safecall; procedure Main; begin // 여기에서 우리는 익명 메소드를 정의한다. 그리고 나서, 이것을 일치하는 WinUI 인터페이스 타입으로 변환한다. var CallbackProc: TCallbackProc := procedure (p: IApplicationInitializationCallbackParams) safecall begin // 먼저, 우리가 정의해 둔 파생 클래스를 하나 생성한다. AppOuter := TDerivedApp.Create as IApplicationOverrides; // 그 다음, IApplicationFactory를 하나 얻어낸다… var Factory := TApplication.Factory; // … 이 팩토리를 사용하여 IApplication을 둘러싸는 랩퍼인 AppWrapper 하나와 // IApplicationOverrides을 구현하는 내부 오브젝트 하나를 얻어낸다. AppWrapper := Factory.CreateInstance(AppOuter, AppInner); // 내부 오브젝트를 외부 오브젝트 안에 둔다. 그러면, // 우리는 필요할 때 내부 오브젝트의 기반 기능을 호출할 수 있다. AppOuter.Inner := AppInner as IApplicationOverrides; end; var AppInitCallback := ApplicationInitializationCallback(CallbackProc); TApplication.Start(AppInitCallback); end; 이 애플리케이션을 사용자 정의하는 코드는 아래 클래스에서 가져온다. type TDerivedApp = class(TInspectableObject, IApplicationOverrides) private FInner: IApplicationOverrides; public // IApplicationOverrides 메소드(들) procedure OnLaunched(args: ILaunchActivatedEventArgs); safecall; ... property Inner: IApplicationOverrides read FInner write FInner; end; The OnLaunched method is then at liberty to do all the app setup required. In this case we create and set up a Window – https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.window and populate it with some controls, creating the following UI: OnLaunched 메소드는 이제 해당 앱에서 필요한 모든 설정을 자유롭게 할 수 있다. 이 데모에서는 창(https://docs.microsoft.com/en-us/windows/winui/api/microsoft.ui.xaml.window)을 하나 생성하여 설정하고 나서 컨트롤 몇개를 넣어서 다음과 같은 UI를 만든다: Look in the code for all the details of what goes on, but in summary: 코드를 들여다보면 어떻게 돌아가는 지 모든 내용을자세히 볼 수 있다. 하지만, 간단히 요약하자면: We create a StackPanel control and put it in the window, then a button is created with a Click event handler and added to the StackPanel. Next we use some XAML to create another StackPanel and a button child control, again with a Click event handler, adding the StackPanel to the window. That gives us 2 approaches to achieve the same goal. Finally some more XAML is used to create a Grid and within that a TextBlock, which then has a couple of event handlers added for OnPointerEntered and OnPointerExited. Ultimately we end up with a window showing a couple of buttons and a text block. The buttons can be clicked to change their caption and the text block changes color when you move the mouse into and out of it. 우리는 StackPanel 컨트롤을 만들어서 창 안에 둔다. 그 다음, Click 이벤트 핸들러가 있는 버튼이 하나 생성되어서 StackPanel에 추가된다. 그 다음, XAML을 사용하여 StackPanel을 또 하나 만들고, 그 안에 자식 컨트롤로 버튼을 하나 넣는다. 이 버튼도 Click 이벤트 핸들러를 가지도록 한다. StackPanel를 창에 추가한다. 동일한 결과를 만들지만 방법은 다른 2가지를 보여주는 것이다. 마지막으로, XAML을 사용하여 Grid를 생성하고 그 안에 TextBlock을 넣는다. 여기에는 OnPointerEntered와 OnPointerExited 이벤트를 처리할 이벤트 핸들러를 넣는다. 궁극적으로 만들어지는 것은 창 하나, 그리고 그 안에 있는 버튼 2개와 텍스트 블록 1개이다. 버튼을 클릭하면 그 버튼의 캡션이 달라지고, 텍스트 블록은 마우스가 들어오거나 나감에 따라 색상이 바뀐다. Notice that for dynamically created UI controls (like the first button), the event handlers can be associated directly, while when the controls are created loading a XAML configuration, the code needs to locate the matching object to associate an event handler with it. (위에 있는 첫번째 버튼과 같이) 동적으로 생성되는 UI 컨트롤은 해당 이벤트 핸들러를 직접 연결시킬 수 있다. 하지만, XAML 구성을 로딩하여 컨트롤을 동적으로 생성하는 경우에는 일치하는 오브젝트를 코드에서 먼저 찾고 나서 해당 이벤트 핸들러를 연계해야 한다. Note: unlike C# and C++ the language projection for Delphi does not currently incorporate all the various interfaces implemented by WinRT and WinUI 3 objects into unified proxy classes, and so there is a lot more interface work going on than would be the case elsewhere. 참고: C# 및 C++와 달리 델파이의 언어 프로젝션은 WinRT와 WinUI 3 오브젝트에서 구현된 다양한 인터페이스들을 현재 일원화된 프록시 클래스로 통합하지 않기 때문에 훨씬 더 많은 인터페이스 작업이 진행되고 있다. 다음 단계 (What’s Next) This demo of the use of Win UI 3 in a packaged or a non-packaged Delphi 11 application is primarily meant for anyone who wants to experiment with this new UI technology from the Delphi point of view. As Embarcadero we are tracking the evolution of WinUI 3 and planning how to support it in the future. Microsoft has announced future support for hosting WinUI 3 controls within a traditional Windows form handle (that is, a VCL or FMX app) via XAML Islands for Win UI 3 — a feature expected for late 2022, so it is quite early for us to discuss a plan for a smoother integration. Stay tuned. WinUI 3을 사용하여 "패키지되는" 또는 "패키지되지 않는" 델파이 11 애플리케이션을 만드는 방법을 이 데모에서 보여주었다. 이 데모의 주 목적은 마이크로소프트에서 내놓은 새 UI 기술인 WinUI 3을 실험하고자 하는 모든 사람들을 위해 해당 기술을 델파이 관점에서 풀어보는 것이다. 엠바카데로는 WinUI 3가 진화되는 추이를 살펴보고 있으며 이 기술을 향후에 어떻게 지원할 지를 계획하고 있다. 마이크로소프트는 WinUI 3 용 XAML 아일랜드(Island)를 통해서 WinUI 3 컨트롤들을 전통적인 윈도우 폼 핸들(즉, VCL 또는 FMX 앱)에 넣어서 쓸 수 있도록 지원할 예정이라고 발표했다. 이 지원은 2022년 후반이 될 것으로 예상되므로, 지금부터 이 기술을 더 자연스럽게 받아드릴 계획을 논하는 것은 너무 이른 감이 있다. 계속 지켜보기 바란다. 인용하기 이 댓글 링크 다른 사이트에 공유하기 더 많은 공유 선택 사항
Recommended Posts
이 토의에 참여하세요
지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.