次の方法で共有


Windows 11 用のデスクトップ アプリでマイカまたはアクリルの素材を適用する

Windows 11 の素材とは、現実世界の人工物に似た UI サーフェスに適用されるビジュアル効果です。 マイカやアクリルなどのオクルード素材は、対話型 UI コントロールの下で、基本レイヤーとして使用されます。

マイカは、ユーザーのテーマとデスクトップの壁紙を組み込み、高度にカスタマイズされた外観を作成する不透明な素材です。 マイカは、視覚エフェクトを作成するために背景の壁紙を 1 回しかキャプチャしないため、パフォーマンス向けに設計されており、特にタイトル バー領域で、アプリの基礎レイヤーに適しています。

アクリルは、すりガラスの効果を再現する、半透明の素材です。 これは、ポップアップやコンテキスト メニューなどの、軽量な一時表示サーフェスにのみ使用されます。

この記事では、Windows App SDK/WinUI XAML アプリのベース レイヤーとして Mica または Acrylic を適用する方法について説明します。

背景素材の使用方法

WinUI 3 ギャラリー アプリを使用すると、WinUI 3 のコントロール、機能、機能の対話型の例を調べて参照できます。 Microsoft Store からアプリを取得するか、GitHub でソース コードを取得します。

マイカまたはアクリル素材をアプリに適用するには、 SystemBackdrop プロパティを XAML SystemBackdrop (通常は、組み込みの背景の 1 つである MicaBackdrop または DesktopAcrylicBackdrop) に設定します。

これらの要素には、 SystemBackdrop プロパティがあります。

これらの例では、XAML とコードでシステムの背景を設定する方法を示します。

マイカ

マイカは通常、アプリ ウィンドウの背景として使用されます。

<Window
    ... >

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

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

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

アクリル

アクリルは通常、ポップアップなどの一時的な UI の背景として使用されます。

<Flyout
    ... >

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

アプリ内アクリル

XAML AcrylicBrush または定義済みの AcrylicBrush テーマ リソースを使用して、アプリ内アクリルをアプリのサーフェイスに適用できます。

WinUI には、アプリのテーマを尊重し、必要に応じて純色にフォールバックするブラシ テーマ リソースのコレクションが含まれています。 特定のサーフェスを描画するには、他のブラシ リソースを適用するのと同様に、テーマ リソースの 1 つを要素の背景に適用します。

<Grid Background="{ThemeResource AcrylicInAppFillColorDefaultBrush}">

これらのリソースは、microsoft-ui-xaml GitHub リポジトリの AcrylicBrush テーマ リソース ファイルで表示できます。

カスタム アクリル ブラシ

アプリのアクリルに色の濃淡を追加してブランドを表示したり、ページ上の他の要素と視覚的なバランスを取ったりすることができます。 グレースケールではなく色を表示するには、次のプロパティを使用して独自のアクリル ブラシを定義する必要があります。

  • TintColor: 色/濃淡のオーバーレイ レイヤーです。
  • TintOpacity: 濃淡レイヤーの不透明度です。
  • TintLuminosityOpacity: 背景からアクリル表面を通して許可される彩度の量を制御します。
  • FallbackColor: バッテリー節約機能でアクリルと置き換わる単色です。 バックグラウンド アクリルの場合、アプリがアクティブなデスクトップ ウィンドウにない場合は、フォールバックカラーによってアクリルも置き換えられます。

淡色テーマのアクリルの見本

濃色テーマのアクリルの見本

明るさの不透明度と濃淡の不透明度の比較

アクリル ブラシを追加するには、ダーク テーマ、ライト テーマ、ハイ コントラスト テーマの 3 つのリソースを定義します。 高コントラストでは、濃色/明るい AcrylicBrush と同じを持つ x:Key を使用することをお勧めします。

TintLuminosityOpacity値を指定しない場合、システムは TintColor と TintOpacity に基づいて値を自動的に調整します。

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <AcrylicBrush x:Key="MyAcrylicBrush"
            TintColor="#FFFF0000"
            TintOpacity="0.8"
            TintLuminosityOpacity="0.5"
            FallbackColor="#FF7F0000"/>
    </ResourceDictionary>

    <ResourceDictionary x:Key="HighContrast">
        <SolidColorBrush x:Key="MyAcrylicBrush"
            Color="{ThemeResource SystemColorWindowColor}"/>
    </ResourceDictionary>

    <ResourceDictionary x:Key="Light">
        <AcrylicBrush x:Key="MyAcrylicBrush"
            TintColor="#FFFF0000"
            TintOpacity="0.8"
            TintLuminosityOpacity="0.5"
            FallbackColor="#FFFF7F7F"/>
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

次のサンプルは、コードで AcrylicBrush を宣言する方法を示しています。

AcrylicBrush myBrush = new AcrylicBrush();
myBrush.TintColor = Color.FromArgb(255, 202, 24, 37);
myBrush.FallbackColor = Color.FromArgb(255, 202, 24, 37);
myBrush.TintOpacity = 0.6;

grid.Fill = myBrush;

システムの背景コントローラーを使用する方法

Windows アプリ SDK 1.3 以降では、前のセクションで説明したように、Window.SystemBackdrop プロパティを XAML SystemBackdrop に設定することで、素材を適用できます。 素材を適用するにはこの方法をお勧めします。

この記事の残りの部分では、Composition MicaControllerDesktopAcrylicController API の使用方法について説明します。

アプリで背景素材を使用するには、ISystemBackdropController インターフェイス (MicaController または DesktopAcrylicController) を実装するコントローラーのいずれかを使用できます。 これらのクラスは、システム背景素材のレンダリングと、素材に関するシステム ポリシーの処理の両方を管理します。

背景素材としてマイカを使用するには、MicaController オブジェクトを作成します。 アクリルを使用するには、DesktopAcrylicController オブジェクトを作成します。 セットアップとサポートのコードは、システム背景素材の種類ごとに同じです。

このコードでは、MicaController を作成する方法を示します。

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();
        ...
    }
}

マイカの Mica Alt バリアントを使用するには、MicaController オブジェクトを作成し、Kind プロパティを MicaKind.BaseAlt に設定します。

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);
        ...
    }
}

このコードでは、DesktopAcrylicController を作成する方法を示します。

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();
        ...
    }
}

コントローラーは、既定でシステムのライト テーマとダーク テーマに反応します。 この動作をオーバーライドするには、コントローラーに次のプロパティを設定します。

コントローラーの 4 つのプロパティのいずれかをカスタマイズした後、関連付けられている SystemBackdropConfiguration.Theme が変更されたときに、既定の Light または Dark 値が適用されなくなります。 これらのプロパティは、新しいテーマに合わせて手動で更新する必要があります。

アプリで背景素材を使用するには、次の項目が必要です。

  • システムのサポート

    アプリが実行されるシステムで、背景素材がサポートされている必要があります。 背景素材が実行時にサポートされていることを確認するには、MicaController.IsSupported または DesktopAcrylicController.IsSupported メソッドを呼び出します。

  • 有効なターゲット

    ICompositionSupportsSystemBackdrop インターフェイスを実装するターゲットを指定する必要があります。 XAML アプリでは、XAML Window がこのインターフェイスを実装しており、背景ターゲットとして使用されます。

  • SystemBackdropConfiguration オブジェクト

    SystemBackdropConfiguration は、システムの背景素材を適切に構成するためのアプリ固有のポリシー情報をシステムの背景コントローラーに提供します。

  • DispatcherQueue オブジェクト

    メイン XAML スレッドで使用可能な Windows.System.DispatcherQueue が必要です。 サンプル コードまたは WindowsSystemDispatcherQueueHelper クラスを参照してください。

例: Windows AppSDK/WinUI アプリで Mica を使用する

この例では、XAML アプリでマイカの背景素材を設定する方法を示します。

ヒント

また、GitHub で次のプロジェクト例を参照してください。

C#: WinUI3 ギャラリーの SampleSystemBackdropsWindow

C++/WinRT: 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;
        }
    }
    ...
};
...