Windows 11 向け Win32 デスクトップ アプリでマイカを適用する

マイカは、ユーザーのテーマとデスクトップの壁紙を組み込み、高度にカスタマイズされた外観を作成する不透明な素材です。 ユーザーが画面上でウィンドウを動かすと、マイカ素材が動的に適応し、アプリケーションの下にある壁紙を使用して豊富な視覚エフェクトを作成します。 さらに、この素材は、アプリが非アクティブな場合に中間色に戻ることで、ユーザーが現在のタスクに集中するのに役立ちます。

この記事では、マイカを Win32 アプリの基本レイヤーとして適用し、タイトル バー領域でのアプリケーションと可視性を優先する方法を説明します。 マイカを使用したアプリのレイヤー化について詳しくは、「マイカ素材」をご覧ください。

前提条件

Windows 11 向け Win32 アプリにマイカを適用するには、Windows App SDK を使う必要があります。 次が必要です。

Win32 アプリでマイカを使用する方法

アプリでマイカを使うには、MicaController クラスを使います。 このクラスは、システム背景素材のレンダリングと、マイカ素材に関するシステム ポリシーの処理の両方を管理します。

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

ヒント

このセクションのコードは、GitHub の Windows App SDK Win32 マイカ サンプルのものです。 完全なコードについては、GitHub リポジトリをご覧ください。 これらの例では、C++/WinRT を使います。

マイカを有効にするには、Windows App SDK、コンポジターDispatcherQueue への参照が必要です。

この例では、パッケージ化されていないアプリを設定するために以下のことを行う方法を示します。

WinMain.cpp から

int __stdcall WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE,  _In_ PSTR, _In_ int)
{
    // Initialize WinRt Instance
    winrt::init_apartment();

    // Enable referencing the WindowsAppSDK from an unpackaged app.
    Utilities::WindowsAppSDKBootstrapperContext sdkContext;

    // Register Window class before making the window.
    MicaWindow::RegisterWindowClass();

    // Mica requires a compositor, which also requires a dispatcher queue.
    auto controller = Utilities::CreateDispatcherQueueControllerForCurrentThread();
    auto compositor = winrt::Compositor();

    // Create your window...
    ...
}

MicaWindow.cpp から

void MicaWindow::RegisterWindowClass()
{
    auto instance = winrt::check_pointer(GetModuleHandleW(nullptr));
    WNDCLASSEX wcex = { sizeof(wcex) };
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = instance;
    wcex.hIcon = LoadIconW(instance, IDI_APPLICATION);
    wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszClassName = ClassName.c_str();
    wcex.hIconSm = LoadIconW(wcex.hInstance, IDI_APPLICATION);
    winrt::check_bool(RegisterClassExW(&wcex)); // check if the window class was registered successfully
}

winrt::init_apartment メソッドは既定ではマルチスレッドです。 WebView2 サンプルのように、シングルスレッドが必要なアプリの場合は、種類を簡単に設定できます。

winrt::init_apartment(winrt::apartment_type::single_threaded);

これで、CreateWindowEx() 関数を使ってウィンドウを作成できます。 次に、ウィンドウ ターゲットを作成し、それをルートとして設定して、マイカを適用するレイヤーを指定する必要があります。 最後に、ウィンドウとターゲットによってマイカがサポートされていることをアサートします。

Win32 マイカ サンプルでは、この処理を行うために DesktopWindowMicaWindow クラスを作成します。 これらのクラスでは、ClassNamewindowTitlem_targetm_micaControllerm_isMicaSupported が定義されています。

WinMain.cpp から

// Mica window is inherited from the MicaWindow class, which is an extension of the DesktopWindow Class.
// Here, we initialize the main window and set the title.
   auto window = MicaWindow(compositor, L"Hello, Mica!");

MicaWindow.cpp から

// Create the main window and enable Mica.
MicaWindow::MicaWindow(const winrt::Compositor& compositor, const std::wstring& windowTitle)
{
    auto instance = winrt::check_pointer(GetModuleHandleW(nullptr));
    WINRT_ASSERT(!m_window); // check that window is not initialized
    WINRT_VERIFY(
        // Window Properties
        CreateWindowExW(
            WS_EX_COMPOSITED,
            ClassName.c_str(), // declared in MicaWindow.h and defined above
            windowTitle.c_str(),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT, 
            800, 600, 
            nullptr, 
            nullptr, 
            instance, 
            this
        ));

    // Check that the window was created successfully.
    WINRT_ASSERT(m_window);

    ShowWindow(m_window, SW_SHOWDEFAULT);
    UpdateWindow(m_window);

    // The Mica controller needs to set a target with a root to recognize the visual base layer.
    m_target = CreateWindowTarget(compositor);

    // Need to set a root before we can enable Mica.
    m_target.Root(compositor.CreateContainerVisual());

    m_micaController = winrt::MicaController();
    m_isMicaSupported = m_micaController.SetTarget(winrt::Microsoft::UI::WindowId{ reinterpret_cast<uint64_t>(m_window) }, m_target);
}

Win32 WebView2 アプリでマイカを使用する方法

マイカを適用する基本的な原則は、ほとんどの Win32 アプリケーションで同じです。 WebView2 でのプロセスは、前に示した Win32 の説明の基本的な手順に従います。 ただし、この場合は、WinRT の init_apartment 機能からシングルスレッド プロセスを指定する必要があります。

ヒント

このセクションのコードは、GitHub の Windows App SDK WebView2 マイカ サンプルのものです。 完全なコードについては、GitHub リポジトリをご覧ください。

作業を始めるには、必要なアパートメント、コントローラー、コンポジター、ターゲット、ルートを設定します。 WinRT の init_apartment 関数は既定ではマルチスレッドですが、WebView2 は本質的にシングルスレッドです。 init_apartment をシングルスレッドとして設定するには、winrt::apartment_type::single_threaded パラメーターを渡します。 マイカ WebView2 サンプルでは、次のコードで参照される Web ビュー関数用に別のクラスを作成することで、構文を簡略化します。

Main.cpp から

int __stdcall WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PSTR, _In_ int)
{
    winrt::init_apartment(winrt::apartment_type::single_threaded);
    // Enable referencing the WindowsAppSDK from an unpackaged app.
    // Remember to have a matching Microsoft.WindowsAppRuntime.Redist installed.
    // https://learn.microsoft.com/windows/apps/windows-app-sdk/deploy-unpackaged-apps
    Utilities::WindowsAppSDKBootstrapperContext sdkContext;
    CompositionWindow::RegisterWindowClass();
    // A dispatcher queue is required to be able to create a compositor.
    auto controller = Utilities::CreateDispatcherQueueControllerForCurrentThread();
    auto compositor = winrt::Compositor();
    auto window = WebView2Window(compositor, L"Hello, WebView2!");

    ...
}

WebView2Window クラスおよびその Mica との統合に関する完全なデモンストレーションについては、GitHub の Windows App SDK WebView2 マイカ サンプルを参照してください。 CompositionWindowWebView2Window クラスがメッセージを処理し、Web ビュー環境を初期化し、ウィンドウが閉じられたらウィンドウ コントローラーを削除する方法に注意してください。

素材レイヤー化と昇格Windows App SDK マイカ サンプル