Anwenden von Mica- oder Acrylmaterialien in Desktop-Apps für Windows 11

Materialien in Windows 11 sind visuelle Effekte, die auf UX-Oberflächen (User Experience, Benutzererfahrung) angewendet bewirken, dass diese wie reale Artefakte aussehen. Verdeckende Materialien wie Acryl und Mica werden als Basisebenen unter interaktiven Benutzeroberflächen-Steuerelementen verwendet.

Mica ist ein undurchsichtiges Material, das das Design und das Desktophintergrundbild der Benutzer*innen enthält, um ein sehr personalisiertes Aussehen zu schaffen. Mica ist für Leistung konzipiert, da es das Hintergrundbild nur einmal erfasst, um die Visualisierung zu erstellen. Es wird daher für die Basisebene Ihrer App und insbesondere für den Titelleistenbereich empfohlen.

Acryl ist ein semitransparentes Material, das einen Milchglaseffekt erzeugt. Es wird nur für kurzlebige Oberflächen mit einfachem Ausblenden wie Flyouts und Kontextmenüs verwendet.

In diesem Artikel wird beschrieben, wie Sie Mica oder Acryl als Basisebene Ihrer Windows App SDK-/WinUI 3 (Windows-UI-Bibliothek)-XAML-App anwenden.

Hinweis

Verwenden eines Hintergrundmaterials

Die WinUI 3-Katalog-App umfasst interaktive Beispiele für die meisten WinUI 3-Steuerelemente, -Features und -Funktionen. Laden Sie die App aus dem Microsoft Store herunter, oder rufen Sie den Quellcode auf GitHub ab

Um Mica oder Acrylmaterial auf Ihre App anzuwenden, legen Sie die SystemBackdrop Eigenschaft auf ein XAML-SystemBackdrop (in der Regel eines der integrierten Kulissen, MicaBackdrop oder DesktopAcrylicBackdrop) fest.

Diese Elemente weisen eine SystemBackdrop Eigenschaft auf:

In diesen Beispielen wird gezeigt, wie Sie den Systemhintergrund in XAML und im Code festlegen.

Mica

Mica wird in der Regel als Hintergrund für ein App-Fenster verwendet.

<Window
    ... >

    <Window.SystemBackdrop>
        <MicaBackdrop Kind="BaseAlt"/>
    </Window.SystemBackdrop>

</Window>
public MainWindow()
{
    this.InitializeComponent();

    SystemBackdrop = new MicaBackdrop() 
                        { Kind = MicaKind.BaseAlt };
}

Acrylic

Acryl wird in der Regel als Hintergrund für vorübergehende UI verwendet, z. B. ein Flyout.

<Flyout
    ... >

    <Flyout.SystemBackdrop>
        <DesktopAcrylicBackdrop/>
    </Flyout.SystemBackdrop>
</Flyout>
Flyout flyout = new Flyout()
{
    SystemBackdrop = new DesktopAcrylicBackdrop()
};

Verwenden eines Systemhintergrundcontrollers

Hinweis

Ab Windows App SDK 1.3 können Sie Material anwenden, indem Sie die Window.SystemBackdrop-Eigenschaft wie im vorherigen Abschnitt beschrieben auf einen XAML-SystemBackdrop festlegen. Dies ist die empfohlene Methode zum Anwenden eines Materials.

Im Rest dieses Artikels wird gezeigt, wie Sie die Composition-MicaController- und DesktopAcrylicController-APIs verwenden.

Um ein Hintergrundmaterial in Ihrer App zu verwenden, können Sie einen der Controller verwenden, die die ISystemBackdropController-Schnittstelle implementieren (MicaController oder DesktopAcrylicController). Diese Klassen verwalten sowohl das Rendern des Systemhintergrundmaterials als auch die Behandlung von Systemrichtlinien für das Material.

Um Mica als Hintergrundmaterial zu verwenden, erstellen Sie ein MicaController-Objekt. Zum Verwenden von Acryl erstellen Sie ein DesktopAcrylicController-Objekt. Die Einrichtung und der unterstützende Code sind für jeden Typ von Systemhintergrundmaterial gleich.

Dieser Code zeigt, wie Sie einen MicaController erstellen.

MicaController m_backdropController;

bool TrySetSystemBackdrop()
{
    if (MicaController.IsSupported())
    {
        ...
        m_backdropController = new MicaController();
        ...
    }
}
// namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops;

winrt::MUCSB::MicaController m_backdropController{ nullptr };

void SetBackground()
{
    if (winrt::MUCSB::MicaController::IsSupported())
    {
        ...
        m_backdropController = winrt::MUCSB::MicaController();
        ...
    }
}

Wenn Sie die Mica Alt-Variante von Mica verwenden möchten, erstellen Sie ein MicaController-Objekt, und legen Sie die Kind-Eigenschaft auf MicaKind.BaseAlt fest.

MicaController m_backdropController;

bool TrySetSystemBackdrop()
{
    if (MicaController.IsSupported())
    {
        ...
        m_backdropController = new MicaController()
        {
            Kind = MicaKind.BaseAlt
        };
        ...
    }
}
// namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops;

winrt::MUCSB::MicaController m_backdropController{ nullptr };

void SetBackground()
{
    if (winrt::MUCSB::MicaController::IsSupported())
    {
        ...
        m_backdropController = winrt::MUCSB::MicaController();
        m_backdropController.Kind(winrt::MUCSB::MicaKind::BaseAlt);
        ...
    }
}

Dieser Code zeigt, wie Sie einen DesktopAcrylicController erstellen.

DesktopAcrylicController m_backdropController;

bool TrySetSystemBackdrop()
{
    if (DesktopAcrylicController.IsSupported())
    {
        ...
        m_backdropController = new DesktopAcrylicController();
        ...
    }
}
// namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops;

winrt::MUCSB::DesktopAcrylicController m_backdropController{ nullptr };

void SetBackground()
{
    if (winrt::MUCSB::DesktopAcrylicController::IsSupported())
    {
        ...
        m_backdropController = winrt::MUCSB::DesktopAcrylicController();
        ...
    }
}

Der Controller reagiert standardmäßig auf die Systemdesigns „Hell“ und „Dunkel“. Sie können dieses Verhalten außer Kraft setzen, indem Sie die folgenden Eigenschaften für den Controller festlegen:

Um das Hintergrundmaterial in Ihrer App verwenden zu können, benötigen Sie Folgendes:

  • Systemunterstützung

    Das System, auf dem die App ausgeführt wird, muss das Hintergrundmaterial unterstützen. Rufen Sie die Methode MicaController.IsSupported oder DesktopAcrylicController.IsSupported auf, um sicherzustellen, dass das Hintergrundmaterial zur Laufzeit unterstützt wird.

  • Ein gültiges Ziel

    Sie müssen ein Ziel bereitstellen, das die ICompositionSupportsSystemBackdrop-Schnittstelle implementiert. In einer XAML-App implementiert das XAML-Window-Objekt diese Schnittstelle und wird als Hintergrundziel verwendet.

  • Ein SystemBackdropConfiguration-Objekt

    Das SystemBackdropConfiguration-Objekt stellt App-spezifische Richtlinieninformationen für den Systemhintergrundcontroller bereit, damit er das Systemhintergrundmaterial korrekt konfigurieren kann.

  • Ein DispatcherQueue-Objekt

    Sie benötigen eine verfügbare Windows.System.DispatcherQueue für den XAML-Hauptthread. Sehen Sie sich dazu die WindowsSystemDispatcherQueueHelper-Klasse im Beispielcode oder das Beispiel im WinUI 3-Katalog an.

Beispiel: Verwenden von Mica in einer Windows App SDK-/WinUI 3-App

In diesem Beispiel wird gezeigt, wie Sie das Mica-Hintergrundmaterial in einer XAML-App einrichten.

Tipp

Sehen Sie sich auch die folgenden Beispielprojekte auf GitHub an:

C#: SampleSystemBackdropsWindow im WinUI 3-Katalog

C++/WinRT: Mica-Beispiel für das Windows App SDK

using Microsoft.UI.Composition.SystemBackdrops;
using Microsoft.UI.Xaml;
using System.Runtime.InteropServices; // For DllImport
using WinRT; // required to support Window.As<ICompositionSupportsSystemBackdrop>()

public sealed partial class MainWindow : Window
{
    WindowsSystemDispatcherQueueHelper m_wsdqHelper; // See below for implementation.
    MicaController m_backdropController;
    SystemBackdropConfiguration m_configurationSource;

    public MainWindow()
    {
        this.InitializeComponent();

        TrySetSystemBackdrop();
    }

    bool TrySetSystemBackdrop()
    {
        if (Microsoft.UI.Composition.SystemBackdrops.MicaController.IsSupported())
        {
            m_wsdqHelper = new WindowsSystemDispatcherQueueHelper();
            m_wsdqHelper.EnsureWindowsSystemDispatcherQueueController();

            // Create the policy object.
            m_configurationSource = new SystemBackdropConfiguration();
            this.Activated += Window_Activated;
            this.Closed += Window_Closed;
            ((FrameworkElement)this.Content).ActualThemeChanged += Window_ThemeChanged;

            // Initial configuration state.
            m_configurationSource.IsInputActive = true;
            SetConfigurationSourceTheme();

            m_backdropController = new Microsoft.UI.Composition.SystemBackdrops.MicaController();

            // Enable the system backdrop.
            // Note: Be sure to have "using WinRT;" to support the Window.As<...>() call.
            m_backdropController.AddSystemBackdropTarget(this.As<Microsoft.UI.Composition.ICompositionSupportsSystemBackdrop>());
            m_backdropController.SetSystemBackdropConfiguration(m_configurationSource);
            return true; // succeeded
        }

        return false; // Mica is not supported on this system
    }

    private void Window_Activated(object sender, WindowActivatedEventArgs args)
        {
            m_configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;
        }

    private void Window_Closed(object sender, WindowEventArgs args)
        {
            // Make sure any Mica/Acrylic controller is disposed
            // so it doesn't try to use this closed window.
            if (m_backdropController != null)
            {
                m_backdropController.Dispose();
                m_backdropController = null;
            }
            this.Activated -= Window_Activated;
            m_configurationSource = null;
        }

    private void Window_ThemeChanged(FrameworkElement sender, object args)
        {
            if (m_configurationSource != null)
            {
                SetConfigurationSourceTheme();
            }
        }

    private void SetConfigurationSourceTheme()
        {
            switch (((FrameworkElement)this.Content).ActualTheme)
            {
                case ElementTheme.Dark: m_configurationSource.Theme = Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Dark; break;
                case ElementTheme.Light: m_configurationSource.Theme = Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Light; break;
                case ElementTheme.Default: m_configurationSource.Theme = Microsoft.UI.Composition.SystemBackdrops.SystemBackdropTheme.Default; break;
            }
        }
}

class WindowsSystemDispatcherQueueHelper
{
    [StructLayout(LayoutKind.Sequential)]
    struct DispatcherQueueOptions
    {
        internal int dwSize;
        internal int threadType;
        internal int apartmentType;
    }

    [DllImport("CoreMessaging.dll")]
    private static extern int CreateDispatcherQueueController([In] DispatcherQueueOptions options, [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object dispatcherQueueController);

    object m_dispatcherQueueController = null;
    public void EnsureWindowsSystemDispatcherQueueController()
    {
        if (Windows.System.DispatcherQueue.GetForCurrentThread() != null)
        {
            // one already exists, so we'll just use it.
            return;
        }

        if (m_dispatcherQueueController == null)
        {
            DispatcherQueueOptions options;
            options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
            options.threadType = 2;    // DQTYPE_THREAD_CURRENT
            options.apartmentType = 2; // DQTAT_COM_STA

            CreateDispatcherQueueController(options, ref m_dispatcherQueueController);
        }
    }
}
// pch.h
...
#include <winrt/Microsoft.UI.Composition.SystemBackdrops.h>
#include <winrt/Windows.System.h>
#include <dispatcherqueue.h>

// MainWindow.xaml.h
...
namespace winrt
{
    namespace MUC = Microsoft::UI::Composition;
    namespace MUCSB = Microsoft::UI::Composition::SystemBackdrops;
    namespace MUX = Microsoft::UI::Xaml;
    namespace WS = Windows::System;
}
...
struct MainWindow : MainWindowT<MainWindow>
{
    winrt::MUCSB::SystemBackdropConfiguration m_configuration{ nullptr };
    winrt::MUCSB::MicaController m_backdropController{ nullptr };
    winrt::MUX::Window::Activated_revoker m_activatedRevoker;
    winrt::MUX::Window::Closed_revoker m_closedRevoker;
    winrt::MUX::FrameworkElement::ActualThemeChanged_revoker m_themeChangedRevoker;
    winrt::MUX::FrameworkElement m_rootElement{ nullptr };
    winrt::WS::DispatcherQueueController m_dispatcherQueueController{ nullptr };

    MainWindow::MainWindow()
    {
        InitializeComponent();

        SetBackground();

        m_closedRevoker = this->Closed(winrt::auto_revoke, [&](auto&&, auto&&)
        {
            if (nullptr != m_backdropController)
            {
                m_backdropController.Close();
                m_backdropController = nullptr;
            }

            if (nullptr != m_dispatcherQueueController)
            {
                m_dispatcherQueueController.ShutdownQueueAsync();
                m_dispatcherQueueController = nullptr;
            }
        });
    }

    void SetBackground()
    {
        if (winrt::MUCSB::MicaController::IsSupported())
        {
            // We ensure that there is a Windows.System.DispatcherQueue on the current thread.
            // Always check if one already exists before attempting to create a new one.
            if (nullptr == winrt::WS::DispatcherQueue::GetForCurrentThread() &&
                nullptr == m_dispatcherQueueController)
            {
                m_dispatcherQueueController = CreateSystemDispatcherQueueController();
            }

            // Setup the SystemBackdropConfiguration object.
            SetupSystemBackdropConfiguration();

            // Setup Mica on the current Window.
            m_backdropController = winrt::MUCSB::MicaController();
            m_backdropController.SetSystemBackdropConfiguration(m_configuration);
            m_backdropController.AddSystemBackdropTarget(
                this->m_inner.as<winrt::MUC::ICompositionSupportsSystemBackdrop>());
        }
        else
        {
            // The backdrop material is not supported.
        }
    }

    winrt::WS::DispatcherQueueController CreateSystemDispatcherQueueController()
    {
        DispatcherQueueOptions options
        {
            sizeof(DispatcherQueueOptions),
            DQTYPE_THREAD_CURRENT,
            DQTAT_COM_NONE
        };

        ::ABI::Windows::System::IDispatcherQueueController* ptr{ nullptr };
        winrt::check_hresult(CreateDispatcherQueueController(options, &ptr));
        return { ptr, take_ownership_from_abi };
    }

    void SetupSystemBackdropConfiguration()
    {
        m_configuration = winrt::MUCSB::SystemBackdropConfiguration();

        // Activation state.
        m_activatedRevoker = this->Activated(winrt::auto_revoke,
            [&](auto&&, MUX::WindowActivatedEventArgs const& args)
            {
                m_configuration.IsInputActive(
                    winrt::MUX::WindowActivationState::Deactivated != args.WindowActivationState());
            });

        // Initial state.
        m_configuration.IsInputActive(true);

        // Application theme.
        m_rootElement = this->Content().try_as<winrt::MUX::FrameworkElement>();
        if (nullptr != m_rootElement)
        {
            m_themeChangedRevoker = m_rootElement.ActualThemeChanged(winrt::auto_revoke,
                [&](auto&&, auto&&)
                {
                    m_configuration.Theme(
                        ConvertToSystemBackdropTheme(m_rootElement.ActualTheme()));
                });

            // Initial state.
            m_configuration.Theme(
                ConvertToSystemBackdropTheme(m_rootElement.ActualTheme()));
        }
    }

    winrt::MUCSB::SystemBackdropTheme ConvertToSystemBackdropTheme(
        winrt::MUX::ElementTheme const& theme)
    {
        switch (theme)
        {
        case winrt::MUX::ElementTheme::Dark:
            return winrt::MUCSB::SystemBackdropTheme::Dark;
        case winrt::MUX::ElementTheme::Light:
            return winrt::MUCSB::SystemBackdropTheme::Light;
        default:
            return winrt::MUCSB::SystemBackdropTheme::Default;
        }
    }
    ...
};
...