New api to simplify accessing appwindow functionality through WinUI 3 code
Xaml has a Window API that internally wraps an hwnd. Windows has an AppWindow class that similarly wraps an hwnd in UWP. WinAppSDK has a new AppWindow which wraps an hwnd and works on Desktop.
You can get an AppWindow from a Xaml Window by calling a COM API to get Xaml and then
a DLL export API to convert the hwnd to an AppWindow. This spec adds a simple Window.AppWindow
property to make this much easier and more discoverable.
Xaml Window will expose AppWindow object directly to app developer through an api. Instead of writing a lot of boiler plate code everywhere, app developer can use this api, reducing code bloat, and making appwindow apis easily accessible from WinUI 3 code.
These before and after C# code examples illustrate how this api simplifies integrating appwindow apis in WinUI 3 codebase.
// This is needed to get any Window from inside a Xaml control
var xamlWindow = WindowHelper.GetWindowForElement(this); // api to get window object from UIElement (not a real api)
// unnecessary boiler plate code
var windowId = Win32Interop.GetWindowIdFromWindow(WindowNative.GetWindowHandle(xamlWindow));
var appWindow = AppWindow.GetFromWindowId(windowId);
//calling function foo (not a real appwindow function)
appWindow.foo();
// This is needed to get any Window from inside a Xaml control
var xamlWindow = WindowHelper.GetWindowForElement(this); // api to get window object from UIElement (not a real api)
//calling function foo directly
xamlWindow.AppWindow.foo();
Notice how xamlWindow.AppWindow.foo()
doesn't require additional steps to call the function foo
.
Gets the AppWindow
associated with this Window
.
public Microsoft.UI.Windowing.AppWindow Window.AppWindow { get; }
var xamlWindow = WindowHelper.GetWindowForElement(this);
auto windowSize = xamlWindow.AppWindow.Size;
Mapping an hwnd to an AppWindow causes the hwnd to be subclassed, meaning that the timing of when AppWindow.GetFromWindowId is first called can potentially have a behavioral side effect. To ensure this is predictable, the AppWindow for Xaml's hwnd will be created during the Xaml Window's construction. Note that this could potentially be an observable behavior change from the behavior before the introduction of this API.
New subclassing order with this new feature change:
- ContentAppWindowBridge
↓ - AppWindow
↓ - Xaml Window
↓ - DefaultWndProc
namespace Microsoft.UI.Xaml
{
unsealed runtimeclass Window
{
...
Microsoft.UI.Windowing.AppWindow AppWindow{ get; };
}
}
-
Window.AppWindow api returns reference to the same appwindow object every time. It gets created during xaml window object's creation. There is minimal performance impact observed for this change.
-
Since AppWindow is an abstraction for HWND, its lifetime will be same as that of HWND. The api cannot return null as AppWindow will always be present if Window object is there. If called after window has been closed, it will fail similarly to other WinUI 3 apis and return a failure HRESULT.
-
There will be only one appwindow object per top level HWND, created during Window object creation. No new appwindow objects are created for child windows.
-
Future scope : Since this api is limited to top level HWND, there should be a way to get app window object for top level HWND from one of its nested children HWND which doesn’t require app developer writing a lot of code.