다음을 통해 공유


Windows 11용 Win32 데스크톱 앱에 Mica 적용

Mica는 사용자의 테마와 데스크톱 배경 화면을 통합하여 고도로 개인 설정된 모양을 만드는 불투명 재질입니다. Mica 재질은 사용자가 화면에서 창을 이동할 때 애플리케이션 아래의 배경 화면을 사용하여 풍부한 시각화를 만들도록 동적 조정됩니다. 또한 Mica는 앱이 비활성 상태일 때 중간색으로 대체하여 사용자가 현재 작업에 집중하도록 도와줍니다.

이 문서는 제목 표시줄 영역에서 애플리케이션과 표시 유형을 우선시하여 Win32 앱의 기본 계층으로 Mica를 적용하는 방법을 설명합니다. Mica를 사용한 앱 계층화에 대한 자세한 내용은 Mica 재료를 참조하세요.

전제 조건

Windows 11용 Win32 앱에 Mica를 적용하려면 Windows 앱 SDK를 사용해야 합니다. 다음 항목이 필요합니다.

Win32 앱에서 Mica를 사용하는 방법

앱에서 Mica를 사용하려면 MicaController 클래스를 사용합니다. 이 클래스는 시스템 배경 재료의 렌더링과 Mica 재료에 대한 전체 시스템 정책 처리를 관리합니다.

MicaController는 기본적으로 시스템 밝은 테마 및 어두운 테마에 반응합니다. 이 동작을 재정의하려면 다음 속성을 MicaController에 전달할 수 있습니다.

이 섹션의 코드는 GitHub의 Windows 앱 SDK Win32 Mica 샘플에서 가져왔습니다. 전체 코드는 GitHub 리포지토리를 참조하세요. 다음 예제에서는 C++/WinRT를 사용합니다.

Mica를 활성하려면 Windows 앱 SDK, CompositorDispatcherQueue에 대한 참조가 필요합니다.

이 예에서는 다음을 수행하여 패키지되지 않은 앱을 설정하는 방법을 보여줍니다.

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() 함수를 사용하여 창을 만들 수 있습니다. 그런 다음 창 대상을 만들고 루트로 설정하여 Mica를 적용할 계층을 지정해야 합니다. 마지막으로 Mica가 창과 대상에서 지원되는지 확인합니다.

Win32 Mica 샘플은 이 작업을 수행하기 위해 DesktopWindowMicaWindow 클래스를 만듭니다. 이러한 클래스는 ClassName, windowTitle, m_target, m_micaController, m_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 앱에서 Mica를 사용하는 방법

Mica를 적용하는 기본 원칙은 대부분의 Win32 애플리케이션에서 일관됩니다. WebView2 프로세스는 이전에 표시된 Win32 지침의 기본 단계를 따릅니다. 그러나 이 경우에서는 WinRT의 init_apartment 기능에서 단일 스레드 프로세스를 지정해야 합니다.

이 섹션의 코드는 GitHub의 Windows 앱 SDK WebView2 Mica 샘플에서 가져왔습니다. 전체 코드는 GitHub 리포지토리를 참조하세요.

시작하려면 필요한 아파트, 컨트롤러, 작성기, 대상 및 루트를 설정합니다. 기본적으로 WinRT init_apartment 함수는 다중 스레드이지만 WebView2는 본질적으로 단일 스레드입니다. init_apartment를 단일 스레드로 설정하려면 winrt::apartment_type::single_threaded 매개 변수를 전달합니다. Mica WebView2 샘플에서는 다음 코드에서 참조되는 웹 보기 함수에 대한 별도의 클래스를 만들어 구문을 단순화합니다.

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 앱 SDK WebView2 Mica 샘플을 참조하세요. CompositionWindowWebView2Window 클래스가 메시지를 처리하고, 웹 보기 환경을 초기화하고, 창이 닫히면 창 컨트롤러를 삭제하는 방법에 유의합니다.

재료, 계층화 및 상승, Windows 앱 SDK Mica 샘플