管理应用窗口(Windows 应用 SDK)

本主题包含了一个代码示例部分。

Windows 应用 SDK 提供了方便易用的 Microsoft.UI.Windowing.AppWindow 类。 AppWindow 与框架无关,适用于所有 Windows 应用,包括 Win32、WPF 和 WinForms 等。 可以将 AppWindow 与框架无关的性质与 Microsoft.UI.Xaml.Window 进行对比,后者是 WinUI 3 框架专用的窗口类。 AppWindow 也是通用 Windows 平台 (UWP) Windows.UI.WindowManagement.AppWindow 的一种演进。

Microsoft.UI.Windowing.AppWindow 的 Windows 应用 SDK 版本不依赖于异步模式;并且会向应用提供关于 API 调用是否成功的即时反馈。

另请参阅安装适用于 Windows 应用 SDK 的工具创建第一个 WinUI 3 项目在现有项目中使用 Windows 应用 SDK

AppWindow 类

Microsoft.UI.Windowing.AppWindow 是一种高级窗口化 API,可用于方便易用的窗口化场景。 AppWindow 可与 Windows UI/UX 和其他应用很好地集成。

AppWindow 代表了应用内容的系统托管容器的高级抽象。 这是用于托管内容的容器,当用户在屏幕上调整应用的大小和移动应用时,此容器代表了与用户交互的实体。 如果你熟悉 Win32,则可以将“应用窗口”视为 HWND 的高级抽象。 如果你熟悉 UWP,则可以将“应用窗口”视为 CoreWindow/ApplicationView/Windows.UI.WindowManagement.AppWindow 的替代。

对于 Microsoft.UI.Windowing.AppWindow 的 Windows 应用 SDK 版本,我们仅支持顶级 HWND。 AppWindow 与顶级 HWND 之间存在 1:1 映射关系

AppWindow 对象和 HWND 的生存期相同:AppWindow 在窗口创建后立即可用,并在窗口关闭时销毁。

AppWindowPresenter 类和子类

每个 AppWindow 都应用了一个 AppWindowPresenter(呈现器)。 如果你是以前使用过 Windows.UI.WindowManagement.AppWindow 的 UWP 开发人员,则应该很熟悉此控件,尽管两者的功能和行为不存在 1:1 映射关系。 另请参阅窗口化功能迁移

呈现器是 Win32 应用模型的一个新概念,类似于窗口状态和样式的组合(但并非完全相同)。 某些呈现器中还定义了无法从经典窗口状态和样式属性中检查的 UI/UX 行为(例如自动隐藏标题栏)。

默认情况下,呈现器将由系统创建,并在创建时应用到 AppWindow。 在 Windows 桌面版的 Windows 应用 SDK 1.0 中,呈现器的类型为 OverlappedPresenter,这是 AppWindowPresenter 的一个子类。 应用无需储存呈现器或保留对呈现器的引用,即可在应用另一个呈现器后恢复到窗口的默认呈现器。 这是因为系统会按照与此呈现器所针对的 AppWindow 的生存期大致相同的期限,保留此呈现器的同一实例;同时应用可以使用 AppWindowPresenterKind.Default 参数调用 AppWindow.SetPresenter 方法,从而重新应用此呈现器。

每次只能将一个呈现器应用到一个窗口。 如果尝试将同一个呈现器应用到其他窗口,则会引发异常。 因此,如果你有多个窗口并想要将每个窗口切换到特定的呈现模式,则需要创建多个相同类型的呈现器,然后将每个呈现器应用到相应的窗口。

某些呈现器提供的功能允许用户进行超出应用自身控制范围的更改。 发生此类更改时,将通过受影响 AppWindow 上的 AppWindow.Changed 事件(其中的 AppWindowChangedEventArgs.DidPresenterChange 属性设置为 true)通知应用。 然后,应用应检查所应用呈现器的属性,以确定发生了哪种更改。

应用的呈现器是一个实时对象。 对 AppWindow.Presenter 对象的任何属性的更改会立即生效。

呈现器应用到窗口后不可销毁。 要销毁呈现器对象,请先将另一个呈现器应用到该窗口,然后才能从该窗口中移除要销毁的呈现器。 为此,可将另一个特定的呈现器应用到该窗口,或者使用 AppWindowPresenterKind.Default 参数调用 AppWindow.SetPresenter 方法,从而将系统创建的默认呈现器重新应用到该窗口。 如果为窗口保留了对系统创建的呈现器的引用,则该呈现器将在此时生效(即将会重新应用最初为窗口创建的同一实例)。

可用的呈现器

提供了以下 AppWindowPresenter 派生的呈现器,并且可在所有受支持的操作系统版本上使用。

  • CompactOverlayPresenter。 用于创建具有固定大小、纵横比为 16:9 的“前端显示”窗口,以实现类似于“画中画”的体验。
  • FullScreenPresenter。 实现全屏窗口体验。
  • OverlappedPresenter。 这是由系统创建的默认呈现器,允许请求和响应最小化/最大化/还原操作和状态更改。

UI 框架和 HWND 互操作

AppWindow 类可用于应用中的任何顶级 HWND。 这意味着在使用桌面 UI 框架(包括 WinUI 3)时,可以继续使用该框架的入口点来创建窗口,并附加其内容。 使用该 UI 框架创建窗口后,可以使用Windows 应用 SDK 中提供的窗口化互操作函数(请参阅下文),访问相应的 AppWindow 及其方法、属性和事件。

使用 AppWindow 的部分好处(即使在使用 UI 框架时也不例外)如下:

  • 可轻松进行标题栏自定义,这在默认情况下会保留 Windows 11 UI 体验(圆角、贴靠组浮出控件)。
  • 系统提供的全屏和紧凑叠加(画中画)体验。
  • 适用于某些核心 Win32 窗口化概念的 Windows 运行时 (WinRT) API 外围应用。

代码示例

此代码示例演示了如何使用 Microsoft.UI.Xaml.Window.AppWindow 属性从 WinUI 3 窗口中检索 Microsoft.UI.Windowing.AppWindow。 要使用此示例,请创建一个新的“打包的空白应用(桌面版 WinUI 3)”项目,并将示例代码粘贴到该项目中。

有关如何使用 AppWindow 的更多详细信息,请参阅窗口化库示例

// MainWindow.xaml.cs
private void myButton_Click(object sender, RoutedEventArgs e)
{
    // Retrieve the AppWindow for the current (XAML) WinUI 3 window.
    Microsoft.UI.Windowing.AppWindow appWindow = this.AppWindow;

    if (appWindow != null)
    {
        // With a non-null AppWindow object, you can call its methods
        // to manipulate the window. As an example, let's change the title
        // text of the window.
        appWindow.Title = "Title text updated via AppWindow!";
    }
}
// pch.h
#include <winrt/Microsoft.UI.Windowing.h> // For the AppWindow class.

// mainwindow.xaml.cpp
void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&)
{
    // Retrieve the AppWindow for the current (XAML) WinUI 3 window.
    Microsoft::UI::Windowing::AppWindow appWindow = this->AppWindow();

    if (appWindow)
    {
        // With a non-null AppWindow object, you can call its methods
        // to manipulate the window. As an example, let's change the title
        // text of the window.
        appWindow.Title(L"Title text updated via AppWindow!");
    }
}

适用于版本 1.3 之前的Windows 应用 SDK 版本(或其他桌面应用框架)的代码示例

Windows 应用 SDK 版本 1.3 及更高版本中提供了(上述代码示例中使用的)Microsoft.UI.Xaml.Window.AppWindow 属性。 对于早期版本,可以使用本部分中的对等功能代码示例。

C# 中的检测示例。 适用于窗口化互操作函数的 .NET 包装器作为 Microsoft.UI.Win32Interop 类的方法实现。 另请参阅从 .NET 应用调用互操作 API

C++。 互操作函数在 winrt/Microsoft.ui.interop.h 头文件中定义。

下面的代码示例部分显示了实际的源代码;而对于在给定现有窗口的情况下检索 AppWindow 对象的方案如下:

  1. 检索现有窗口对象的(对应于 UI 框架的)HWND(如果还没有)。
  2. 将 HWND 传递给 GetWindowIdFromWindow 互操作函数以检索 WindowId
  3. 将 WindowId 传递给静态的 AppWindow.GetFromWindowId 方法以检索 AppWindow
// MainWindow.xaml.cs
private void myButton_Click(object sender, RoutedEventArgs e)
{
    // Retrieve the window handle (HWND) of the current (XAML) WinUI 3 window.
    var hWnd =
        WinRT.Interop.WindowNative.GetWindowHandle(this);

    // Retrieve the WindowId that corresponds to hWnd.
    Microsoft.UI.WindowId windowId =
        Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);

    // Lastly, retrieve the AppWindow for the current (XAML) WinUI 3 window.
    Microsoft.UI.Windowing.AppWindow appWindow =
        Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);

    if (appWindow != null)
    {
        // You now have an AppWindow object, and you can call its methods to manipulate the window.
        // As an example, let's change the title text of the window.
        appWindow.Title = "Title text updated via AppWindow!";
    }
}
// pch.h
#include "microsoft.ui.xaml.window.h" // For the IWindowNative interface.
#include <winrt/Microsoft.UI.Interop.h> // For the WindowId struct and the GetWindowIdFromWindow function.
#include <winrt/Microsoft.UI.Windowing.h> // For the AppWindow class.

// mainwindow.xaml.cpp
void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&)
{
    // Retrieve the window handle (HWND) of the current (XAML) WinUI 3 window.
    auto windowNative{ this->m_inner.as<::IWindowNative>() };
    HWND hWnd{ 0 };
    windowNative->get_WindowHandle(&hWnd);

    // Retrieve the WindowId that corresponds to hWnd.
    Microsoft::UI::WindowId windowId = 
        Microsoft::UI::GetWindowIdFromWindow(hWnd);

    // Lastly, retrieve the AppWindow for the current (XAML) WinUI 3 window.
    Microsoft::UI::Windowing::AppWindow appWindow = 
        Microsoft::UI::Windowing::AppWindow::GetFromWindowId(windowId);

    if (appWindow)
    {
        // You now have an AppWindow object, and you can call its methods to manipulate the window.
        // As an example, let's change the title text of the window.
        appWindow.Title(L"Title text updated via AppWindow!");
    }
}

限制

  • AppWindow 是一种 WinUI 3 API。 这意味着它仅适用于桌面应用(打包和未打包);不适用于 UWP 应用。
  • Windows 应用 SDK 目前不提供用于将 UI 框架内容附加到 AppWindow 的方法。 不过可参阅代码示例部分。
  • Windows 11 及更高版本,以及 Windows 10 版本 1.2 及更高版本的 Windows 应用 SDK 支持标题栏自定义。 有关详细信息,请参阅标题栏自定义