タイトル バーのカスタマイズ

Windowsでは、すべてのウィンドウに既定のタイトル バーが用意されており、アプリの個性に合わせてカスタマイズできます。 既定のタイトル バーには、一部の標準コンポーネントと、ウィンドウのドラッグやサイズ変更などのコア機能が付属しています。

A Windows app showing the title bar

アプリの タイトル バー 、許容できるタイトル バー領域のコンテンツ、推奨される UI パターンのカスタマイズに関するガイダンスについては、タイトル バーのデザインに関する記事を参照してください。

タイトル バーのコンポーネント

この一覧では、標準タイトル バーのコンポーネントについて説明します。

  • タイトル バーの四角形
  • タイトル テキスト
  • システム アイコン (UWP を除く)
  • システム メニュー - アプリ アイコンをクリックするか、タイトル バーを右クリックしてアクセスします。
  • キャプション コントロール
    • 最小化ボタン
    • 最大化/復元ボタン
    • [閉じる] ボタン

プラットフォーム オプション

タイトル バーの正確な機能とカスタマイズに使用できるオプションは、UI プラットフォームとアプリの要件によって異なります。 この記事では、WinUI 2 で Windows アプリ SDK、WinUI 3、または UWP を使用するアプリのタイトル バーをカスタマイズする方法について説明します。

Note

Windows アプリ SDKと UWP で使用されるウィンドウ モデルの詳細な比較については、「ウィンドウ機能の移行」を参照してください。

Windows アプリ SDKのウィンドウ機能は、Win32 HWND モデルに基づく Microsoft.UI.Windowing.AppWindow クラスを使用します。 AppWindow とアプリの最上位 HWND の間には、1 対 1 のマッピングがあります。 AppWindow とその関連クラスには、タイトル バーのカスタマイズなど、アプリの最上位ウィンドウのさまざまな側面を管理できる API が用意されています。 Windowsが提供する既定のタイトル バーを変更して UI の残りの部分とブレンドしたり、アプリ キャンバスをタイトル バー領域に拡張して独自のタイトル バーのコンテンツを提供したりできます。

重要

タイトル バーのカスタマイズ API は現在、Windows 11でのみサポートされています。 これらの API を呼び出す前に、コードで AppWindowTitleBar.IsCustomizationSupported を確認して、他のバージョンのWindowsでアプリがクラッシュしないようにすることをお勧めします。

WinUI 3 を使用する XAML アプリの場合、XAML ウィンドウ API を使用すると、Windows 10でも動作するタイトル バーを簡単にカスタマイズできます。 これらの API は、Windows アプリ SDK API と組み合わせて使用できます (WinUI 3 タブを参照)。

AppWindow を使用する方法

Windows アプリ SDKでサポートされている任意の UI フレームワーク (Win32、WPF、WinForms、または WinUI 3) で AppWindow API を使用でき、必要な API のみを使用して段階的に導入できます。 相互運用 API を使用して、既存のウィンドウから AppWindow オブジェクトを取得します。 この AppWindow オブジェクトを使用すると、タイトル バーのカスタマイズ API にアクセスできます。 相互運用 API の詳細については、「 アプリ ウィンドウの管理 - UI フレームワークと HWND 相互運用 機能」および 「Windowing ギャラリーのサンプル」を参照してください。

タイトル バーのカスタマイズ レベル

タイトル バーに適用できるカスタマイズには、既定のタイトル バーに軽微な変更を適用するか、アプリ キャンバスをタイトル バー領域に拡張して完全にカスタム コンテンツを提供するという 2 つのレベルがあります。

シンプル

単純なカスタマイズは、Windows アプリ SDKと UWP/WinUI 2 でのみ使用できます。

タイトル バーの色の変更などの簡単なカスタマイズのために、アプリ ウィンドウのタイトル バー オブジェクトのプロパティを設定して、タイトル バーの要素に使用する色を指定できます。 この場合、アプリのタイトルの描画やドラッグ領域の定義など、タイトル バーの他のすべての側面に対する責任がシステムによって保持されます。

完全

もう 1 つのオプションは、既定のタイトル バーを非表示にして、独自のカスタム コンテンツに置き換える方法です。 たとえば、タイトル バー領域にテキスト、検索ボックス、またはカスタム メニューを配置できます。 また、このオプションを使用して、Mica などの素材の背景をタイトル バー領域に拡張する必要があります。

完全なカスタマイズを選択する場合は、タイトル バー領域にコンテンツを配置する責任があり、独自のドラッグ領域を定義できます。 キャプション コントロール (システムの [閉じる]、[最小化]、[最大化] ボタン) は引き続き使用でき、システムによって処理されますが、アプリ タイトルなどの要素は使用できません。 アプリに必要であれば、このような要素を自身で作成する必要があります。

簡単なカスタマイズ

タイトル バーの色またはアイコンのみをカスタマイズする場合は、アプリ ウィンドウのタイトル バー オブジェクトにプロパティを設定できます。

(Windows 11のみ。詳細については、プラットフォーム オプションを参照してください)。

これらの例では、 AppWindow のインスタンスを取得し、そのプロパティを設定する方法を示します。

Title

既定では、タイトル バーには、アプリの種類がウィンドウ タイトル ("WinUI Desktop" など) として表示されます。 ウィンドウ タイトルを変更するには、 AppWindow.Title プロパティを 1 行のテキスト値に設定します。

using Microsoft.UI;           // Needed for WindowId.
using Microsoft.UI.Windowing; // Needed for AppWindow.
using WinRT.Interop;          // Needed for XAML/HWND interop.

private AppWindow m_AppWindow;

public MainWindow()
{
    this.InitializeComponent();

    m_AppWindow = GetAppWindowForCurrentWindow();
    m_AppWindow.Title = "App title";
}

private AppWindow GetAppWindowForCurrentWindow()
{
    IntPtr hWnd = WindowNative.GetWindowHandle(this);
    WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
    return AppWindow.GetFromWindowId(wndId);
}

この例では、 AppWindowTitleBar のインスタンスを取得し、その色プロパティを設定する方法を示します。

private bool SetTitleBarColors()
{
    // Check to see if customization is supported.
    // Currently only supported on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported())
    {
        if (m_AppWindow is null)
        {
            m_AppWindow = GetAppWindowForCurrentWindow();
        }
        var titleBar = m_AppWindow.TitleBar;

        // Set active window colors
        titleBar.ForegroundColor = Colors.White;
        titleBar.BackgroundColor = Colors.Green;
        titleBar.ButtonForegroundColor = Colors.White;
        titleBar.ButtonBackgroundColor = Colors.SeaGreen;
        titleBar.ButtonHoverForegroundColor = Colors.Gainsboro;
        titleBar.ButtonHoverBackgroundColor = Colors.DarkSeaGreen;
        titleBar.ButtonPressedForegroundColor = Colors.Gray;
        titleBar.ButtonPressedBackgroundColor = Colors.LightGreen;

        // Set inactive window colors
        titleBar.InactiveForegroundColor = Colors.Gainsboro;
        titleBar.InactiveBackgroundColor = Colors.SeaGreen;
        titleBar.ButtonInactiveForegroundColor = Colors.Gainsboro;
        titleBar.ButtonInactiveBackgroundColor = Colors.SeaGreen;
        return true;
    }
    return false;
}

アイコンとシステム メニュー

システム アイコンを非表示にしたり、カスタム アイコンに置き換えたりすることもできます。 右クリックまたはタップすると、システム アイコンにシステム メニューが表示されます。 ダブルクリックまたはタップすると、ウィンドウが閉じます。

システム アイコンと関連する動作を表示または非表示にするには、タイトル バー の IconShowOptions プロパティを設定します。

titleBar.IconShowOptions = IconShowOptions.HideIconAndSystemMenu;

Note

列挙 IconShowOptions 体を使用すると、今後のリリースで他のオプションが追加される可能性があります。 GitHubのWindows アプリ SDK リポジトリに関するフィードバックは、お客様の関心がある場合に提供できます。

カスタム ウィンドウ アイコンを使用するには、 AppWindow.SetIcon メソッドのいずれかを呼び出して、新しいアイコンを設定します。

  • SetIcon(String)

    SetIcon(String) メソッドは現在、.ico ファイルでのみ動作します。 このメソッドに渡す文字列は、.ico ファイルへの完全修飾パスです。

    m_AppWindow.SetIcon("iconPath/iconName.ico");
    
  • SetIcon(IconId)

    CreateIcon などのいずれかのアイコン関数のアイコン (HICON) へのハンドルが既にある場合は、GetIconIdFromIcon 相互運用 API を使用して IconId を取得できます。 その後、SetIcon(IconId) メソッドに渡IconIdして、ウィンドウ アイコンを設定できます。

    m_AppWindow.SetIcon(iconId));
    

タイトル バーの色を設定する際には注意する点がいくつかあります。

  • ボタンの背景色は、閉じるボタンの ホバー押された状態には 適用されません。 [閉じる] ボタンがこれらの状態の場合は、常にシステム定義の色が使用されます。
  • color プロパティを設定すると null 、既定のシステムカラーにリセットされます。
  • 透明色を設定することはできません。 色のアルファ チャネルは無視されます。

Windows では、ユーザーが選択したアクセント カラーをタイトル バーに適用するかどうかをユーザーが指定できます。 タイトル バーの色を設定した場合は、すべての色を明示的に設定することをお勧めします。 これにより、ユーザー定義の色設定によって意図しない色の組み合わせが発生する心配がなくなります。

全面的なカスタマイズ

タイトル バーの全面的なカスタマイズを選択すると、アプリのクライアント領域が拡張され、タイトル バーの領域を含めてウィンドウ全体が対象になります。 ウィンドウによって引き続き提供されるキャプション ボタンを除き、ウィンドウ全体の描画と入力処理を行う必要があります。

既定のタイトル バーを非表示にし、コンテンツをタイトル バー領域に拡張するには、アプリのコンテンツをタイトル バー領域に拡張するプロパティを true[. XAML アプリでは、このプロパティはアプリの OnLaunched メソッド (App.xaml.cs) またはアプリの最初のページで設定できます。

ヒント

すべてのコードを一度に表示するには、「 完全なカスタマイズの例 」セクションを参照してください。

(Windows 11のみ。詳細については、プラットフォーム オプションを参照してください)。

この例では、 AppWindowTitleBar を取得し、 ExtendsContentIntoTitleBar プロパティ trueを .

重要

タイトル バーのカスタマイズ API は、アプリが実行される可能性があるWindowsのすべてのバージョンではサポートされていないため、これらの API を呼び出す前に、必ずコードで AppWindowTitleBar.IsCustomizationSupported を確認してください。 If title bar customization is not supported, you will typically hide your custom title bar UI by setting Visibility to Collapsed.

using Microsoft.UI;           // Needed for WindowId
using Microsoft.UI.Windowing; // Needed for AppWindow
using WinRT.Interop;          // Needed for XAML/HWND interop

private AppWindow m_AppWindow;

public MainWindow()
{
    this.InitializeComponent();

    m_AppWindow = GetAppWindowForCurrentWindow();
    // Check to see if customization is supported.
    // Currently only supported on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported())
    {
        var titleBar = m_AppWindow.TitleBar;
        // Hide default title bar.
        titleBar.ExtendsContentIntoTitleBar = true;
    }
    else
    {
        // Title bar customization using these APIs is currently
        // supported only on Windows 11. In other cases, hide
        // the custom title bar element.
        AppTitleBar.Visibility = Visibility.Collapsed;
    }
}

private AppWindow GetAppWindowForCurrentWindow()
{
    IntPtr hWnd = WindowNative.GetWindowHandle(this);
    WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
    return AppWindow.GetFromWindowId(wndId);
}

タイトル バーのコンテンツとドラッグ領域

アプリがタイトル バー領域に拡張されたら、タイトル バーの UI を定義および管理する必要があります。 通常、これには、タイトル テキストとドラッグ領域を指定する必要があります。 タイトル バーのドラッグ領域は、ユーザーがクリックしてドラッグしてウィンドウを移動できる場所を定義します。 また、ユーザーが右クリックしてシステム メニューを表示することもできます。

許容できるタイトル バーのコンテンツと推奨される UI パターンの詳細については、 タイトル バーのデザインに関するページを参照してください。

(Windows 11のみ。詳細については、プラットフォーム オプションを参照してください)。

コンテンツをタイトル バー領域に拡張すると、既定では、キャプション ボタンをドラッグ領域として除き、タイトル バー領域全体が保持されます。 タイトル バーに対話型コンテンツを配置しない場合は、この既定のドラッグ領域をそのまま使用できます。 タイトル バーに対話型コンテンツを配置する場合は、次のセクションで説明するドラッグ領域を指定する必要があります。

この例では、対話型コンテンツのないカスタム タイトル バー UI の XAML を示します。

<Grid x:Name="AppTitleBar"  
      Height="32">
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
        <ColumnDefinition/>
        <ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
    </Grid.ColumnDefinitions>
    <Image x:Name="TitleBarIcon" Source="/Images/WindowIcon.png"
           Grid.Column="1"
           HorizontalAlignment="Left"
           Width="16" Height="16"
           Margin="8,0,0,0"/>
    <TextBlock x:Name="TitleTextBlock" 
               Text="App title" 
               Style="{StaticResource CaptionTextBlockStyle}"
               Grid.Column="1"
               VerticalAlignment="Center"
               Margin="28,0,0,0"/>
</Grid>

重要

キャプション LeftPaddingColumnRightPaddingColumn ボタンの領域を予約するために使用されます。 これらの列の値は Width 、後で示すコードで設定されます。 コードと説明については、「 システム キャプション ボタン 」セクションを参照してください。

対話型コンテンツ

ボタン、メニュー、検索ボックスなどの対話型のコントロールをアプリの上部に配置して、タイトル バーに表示することもできます。 ただし、対話型要素がユーザー入力を確実に受け取り、ユーザーがウィンドウを移動できるようにするには、いくつかのルールに従う必要があります。

A Windows app with a search box in the title bar

(Windows 11のみ。詳細については、「プラットフォーム オプション」を参照してください)。

タイトル バー領域に対話型コンテンツを追加する場合は、ユーザーが操作できるように、そのコンテンツの周囲に明示的なドラッグ領域を定義する必要があります。 カスタムドラッグ領域を設定すると、既定のドラッグ領域が削除され、システムは必須のドラッグ領域を予約しません。 ユーザーがウィンドウを移動するのに十分なスペースがタイトル バーにあることを確認する責任があります。

ドラッグ領域を設定するには、 AppWindowTitleBar.SetDragRectangles メソッドを 呼び出します。 このメソッドは、ドラッグ領域を定義する四角形の配列を受け取ります。 タイトル バーのサイズが変更されたら、新しいサイズに合わせてドラッグ領域を再計算し、新しい値で呼び出す SetDragRectangles 必要があります。

カスタム タイトル バーが実行されているシステムでサポートされていない場合、カスタム タイトル バーは表示されません。 カスタム タイトル バーに配置した機能には、別の UI を指定する必要があります。

この例では、検索ボックスを含むカスタム タイトル バー UI を示し、検索ボックスの両側でドラッグ四角形を計算および設定する方法を示します。 コードで注目すべき重要な点をいくつか次に示します。

  • グリッドの AppTitleBar 高さを 48 に設定して、対話型コンテンツの タイトル バー のデザイン ガイダンスに従います。
  • ドラッグ四角形の計算を簡単にするには、レイアウトに複数の名前付き列を使用 Grid します。
  • true MainWindow コンストラクターで設定ExtendsContentIntoTitleBarします。 後で呼び出されるコードで設定すると、既定のシステム タイトル バーが最初に表示され、次に非表示になることがあります。
  • 要素が読み込まれた後にドラッグ領域を計算する最初の呼び出しを AppTitleBar 行います (AppTitleBar_Loaded)。 それ以外の場合、計算に使用される要素が正しい値を持つ保証はありません。
  • 要素のサイズAppTitleBar_SizeChanged () が変更された後にのみ、ドラッグ四角形の計算をAppTitleBar更新します。 ウィンドウ Changed イベントに依存している場合は、イベントが発生する前 AppTitleBar にサイズが変更され、計算で正しくない値が使用される状況 (ウィンドウの最大化や最小化など) が発生します。
  • カスタム タイトル バーがサポートされ、使用されていることを確認するには、確認IsCustomizationSupportedExtendsContentIntoTitleBarした後にのみ呼び出SetDragRectanglesします。
<Grid x:Name="AppTitleBar"  
      Height="48">
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
        <ColumnDefinition x:Name="IconColumn" Width="Auto"/>
        <ColumnDefinition x:Name="TitleColumn" Width="Auto"/>
        <ColumnDefinition x:Name="LeftDragColumn" Width="*"/>
        <ColumnDefinition x:Name="SearchColumn" Width="Auto"/>
        <ColumnDefinition x:Name="RightDragColumn" Width="*"/>
        <ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
    </Grid.ColumnDefinitions>
    <Image x:Name="TitleBarIcon" Source="/Images/WindowIcon.png"
           Grid.Column="1"
           Width="16" Height="16"
           Margin="8,0,0,0"/>
    <TextBlock x:Name="TitleTextBlock" 
               Text="App title" 
               Style="{StaticResource CaptionTextBlockStyle}"
               Grid.Column="2"
               VerticalAlignment="Center"
               Margin="4,0,0,0"/>
    <AutoSuggestBox Grid.Column="4" QueryIcon="Find"
                    PlaceholderText="Search"
                    VerticalAlignment="Center"
                    Width="260" Margin="4,0"/>
</Grid>
using System.Runtime.InteropServices;

private AppWindow m_AppWindow;

public MainWindow()
{
    this.InitializeComponent();

    m_AppWindow = GetAppWindowForCurrentWindow();

    // Check to see if customization is supported.
    // Currently only supported on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported())
    {
        var titleBar = m_AppWindow.TitleBar;
        titleBar.ExtendsContentIntoTitleBar = true;
        AppTitleBar.Loaded += AppTitleBar_Loaded;
        AppTitleBar.SizeChanged += AppTitleBar_SizeChanged;
    }
    else
    {
        // Title bar customization using these APIs is currently
        // supported only on Windows 11. In other cases, hide
        // the custom title bar element.
        AppTitleBar.Visibility = Visibility.Collapsed;

        // Show alternative UI for any functionality in
        // the title bar, such as search.
    }

}

private void AppTitleBar_Loaded(object sender, RoutedEventArgs e)
{
    // Check to see if customization is supported.
    // Currently only supported on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported())
    {
        SetDragRegionForCustomTitleBar(m_AppWindow);
    }
}

private void AppTitleBar_SizeChanged(object sender, SizeChangedEventArgs e)
{
    // Check to see if customization is supported.
    // Currently only supported on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported()
        && m_AppWindow.TitleBar.ExtendsContentIntoTitleBar)
    {
        // Update drag region if the size of the title bar changes.
        SetDragRegionForCustomTitleBar(m_AppWindow);
    }
}

private AppWindow GetAppWindowForCurrentWindow()
{
    IntPtr hWnd = WindowNative.GetWindowHandle(this);
    WindowId wndId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
    return AppWindow.GetFromWindowId(wndId);
}

[DllImport("Shcore.dll", SetLastError = true)]
internal static extern int GetDpiForMonitor(IntPtr hmonitor, Monitor_DPI_Type dpiType, out uint dpiX, out uint dpiY);

internal enum Monitor_DPI_Type : int
{
    MDT_Effective_DPI = 0,
    MDT_Angular_DPI = 1,
    MDT_Raw_DPI = 2,
    MDT_Default = MDT_Effective_DPI
}

private double GetScaleAdjustment()
{
    IntPtr hWnd = WindowNative.GetWindowHandle(this);
    WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
    DisplayArea displayArea = DisplayArea.GetFromWindowId(wndId, DisplayAreaFallback.Primary);
    IntPtr hMonitor = Win32Interop.GetMonitorFromDisplayId(displayArea.DisplayId);

    // Get DPI.
    int result = GetDpiForMonitor(hMonitor, Monitor_DPI_Type.MDT_Default, out uint dpiX, out uint _);
    if (result != 0)
    {
        throw new Exception("Could not get DPI for monitor.");
    }

    uint scaleFactorPercent = (uint)(((long)dpiX * 100 + (96 >> 1)) / 96);
    return scaleFactorPercent / 100.0;
}

private void SetDragRegionForCustomTitleBar(AppWindow appWindow)
{
    // Check to see if customization is supported.
    // Currently only supported on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported()
        && appWindow.TitleBar.ExtendsContentIntoTitleBar)
    {
        double scaleAdjustment = GetScaleAdjustment();

        RightPaddingColumn.Width = new GridLength(appWindow.TitleBar.RightInset / scaleAdjustment);
        LeftPaddingColumn.Width = new GridLength(appWindow.TitleBar.LeftInset / scaleAdjustment);

        List<Windows.Graphics.RectInt32> dragRectsList = new();

        Windows.Graphics.RectInt32 dragRectL;
        dragRectL.X = (int)((LeftPaddingColumn.ActualWidth) * scaleAdjustment);
        dragRectL.Y = 0;
        dragRectL.Height = (int)(AppTitleBar.ActualHeight * scaleAdjustment);
        dragRectL.Width = (int)((IconColumn.ActualWidth
                                + TitleColumn.ActualWidth
                                + LeftDragColumn.ActualWidth) * scaleAdjustment);
        dragRectsList.Add(dragRectL);

        Windows.Graphics.RectInt32 dragRectR;
        dragRectR.X = (int)((LeftPaddingColumn.ActualWidth
                            + IconColumn.ActualWidth
                            + TitleTextBlock.ActualWidth
                            + LeftDragColumn.ActualWidth
                            + SearchColumn.ActualWidth) * scaleAdjustment);
        dragRectR.Y = 0;
        dragRectR.Height = (int)(AppTitleBar.ActualHeight * scaleAdjustment);
        dragRectR.Width = (int)(RightDragColumn.ActualWidth * scaleAdjustment);
        dragRectsList.Add(dragRectR);

        Windows.Graphics.RectInt32[] dragRects = dragRectsList.ToArray();

        appWindow.TitleBar.SetDragRectangles(dragRects);
    }
}

警告

AppWindow は、論理座標を使用しない UI フレームワークとの互換性のために物理ピクセルを使用します。 WPF または WinUI 3、、およびLeftInset渡されたSetDragRectangles値を使用する場合は、RightInset表示スケールが 100% でない場合は調整する必要があります。 この例では、表示スケール設定を scaleAdjustment 考慮して値を計算します。

WPF の場合、 Window.DpiChanged イベントを処理して NewDpi 値を取得できます。

WinUI 3 の場合は、前の例に示すように、 プラットフォーム呼び出し (P/Invoke) を使用してネイティブ の GetDpiForMonitor 関数を呼び出します。

ヒント

システム TitleBar (int titleBarHeight = appWindow.TitleBar.Height;) の高さを取得し、これを使用してカスタム タイトル バーとドラッグ領域の高さを設定できます。 ただし、他のコントロールを追加する場合は、 タイトル バーの高さを 48px に設定することをお勧めします。 この場合、システム タイトル バーの高さはコンテンツと一致しないため、代わりにタイトル バー要素の ActualHeight を使用してドラッグ領域の高さを設定します。

システム タイトル ボタン

(Windows 11のみ。詳細については、「プラットフォーム オプション」を参照してください)。

システムは、システム キャプション ボタン (最小化、最大化、復元、閉じる) 用に、アプリ ウィンドウの左上隅または右上隅を予約します。 システムはキャプション ボタン領域の制御を保持して、ウィンドウのドラッグ、最小化、最大化、および閉じのための最小限の機能が提供されることを保証します。 システムは、左から右へと表記される言語では右上、右から左へと表記される言語では左上に [閉じる] ボタンを描画します。

アプリの背景など、キャプションコントロール領域の下にコンテンツを描画することはできますが、ユーザーが操作できると予想される UI は配置しないでください。 タイトル コントロールに対する入力はシステムによって処理されるため、タイトル コントロール領域で入力を受け取ることはできません。

前の例のこれらの行は、タイトル バーを定義する XAML のパディング列を示しています。 余白の代わりに埋め込み列を使用すると、背景がキャプションコントロールボタン(透明ボタンの場合)の下に領域を描画します。 右と左の両方のパディング列を使用すると、タイトル バーが右から左と左から右の両方のレイアウトで正しく動作します。

<Grid.ColumnDefinitions>
    <ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
    <ColumnDefinition/>
    <ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
</Grid.ColumnDefinitions>

タイトル バー UI のレイアウトで説明できるように、キャプションコントロール領域の寸法と位置は AppWindowTitleBar クラスによって伝達されます。 両側の予約領域の幅は LeftInset プロパティまたは RightInset プロパティによって指定され、高さは Height プロパティによって指定されます。

ドラッグ領域を計算して設定するときに、パディング列の幅を指定する方法を次に示します。

// Get caption button occlusion information.
int CaptionButtonOcclusionWidthRight = appWindow.TitleBar.RightInset;
int CaptionButtonOcclusionWidthLeft = appWindow.TitleBar.LeftInset;

// Set the width of padding columns in the UI.
RightPaddingColumn.Width = new GridLength(CaptionButtonOcclusionWidthRight);
LeftPaddingColumn.Width = new GridLength(CaptionButtonOcclusionWidthLeft);

重要

表示のスケーリングがこれらの値にどのように影響するかについては、「 対話型コンテンツ」 セクションの重要な情報を参照してください。

キャプション ボタンの色と透明度

アプリのコンテンツをタイトル バー領域に拡張すると、キャプション ボタンの背景を透明にして、アプリの背景が表示されるようにすることができます。 通常、完全な透明度を得るために背景を Colors.Transparent 設定します。 部分的な透明度の場合は、プロパティを設定する Color アルファ チャネルを設定します。

(Windows 11のみ。詳細については、プラットフォーム オプションを参照してください)。

次のタイトル バープロパティは透明にすることができます。

その他のすべての色プロパティでは、引き続きアルファ チャネルが無視されます。 ExtendsContentIntoTitleBarfalse設定すると、アルファ チャンネルはすべてのAppWindowTitleBarカラー プロパティで常に無視されます。

リファレンス: Colors.TransparentColorHelper

ボタンの背景色は、[閉じる] ボタンの ホバー 状態と 押された状態には 適用されません。 [閉じる] ボタンがこれらの状態の場合は、常にシステム定義の色が使用されます。

ヒント

マイカ は、フォーカスしているウィンドウを区別するのに役立つ楽しい 素材 です。 Windows 11の有効期間が長いウィンドウの背景としてお勧めします。 ウィンドウのクライアント領域に Mica を適用している場合は、タイトルバー領域に拡張し、Mica が表示されるようにキャプション ボタンを透明にすることができます。 詳細については、 マイカの資料 を参照してください。

ウィンドウがアクティブでないときにタイトル バーを暗くする

ウィンドウがアクティブまたは非アクティブな場合は、明確にする必要があります。 少なくとも、タイトル バーのテキスト、アイコン、ボタンの色を変更する必要があります。

イベントを処理してウィンドウのアクティブ化状態を判断し、必要に応じてタイトル バーの UI を更新します。 ウィンドウの状態を決定する方法は、アプリに使用する UI フレームワークによって異なります。

タイトル バーをリセットする

(Windows 11のみ。詳細については、プラットフォーム オプションを参照してください)。

アプリの実行中にシステム タイトル バーをリセットまたは切り替えるには、 AppWindowTitleBar.ResetToDefault を呼び出します。

m_AppWindow.TitleBar.ResetToDefault();

タイトル バーの表示と非表示を切り替える

全画面表示モードまたはコンパクト オーバーレイ モードのサポートをアプリに追加する場合は、アプリがこれらのモードを切り替えるときに、タイトル バーに変更を加える必要がある場合があります。

(Windows 11のみ。詳細については、プラットフォーム オプションを参照してください)。

アプリが 全画面表示 モードで実行されると、システムはタイトル バーとキャプション コントロール ボタンを非表示にします。 AppWindow.Changed イベントを処理し、イベント args DidPresenterChange プロパティを確認して、新しいウィンドウ プレゼンテーションに応答してタイトル バーを表示、非表示、または変更するかどうかを確認できます。

この例では、イベントを処理して、前の Changed 例の要素を AppTitleBar 表示および非表示にする方法を示します。 ウィンドウが コンパクト オーバーレイ モードの場合、タイトル バーは既定のシステム タイトル バーにリセットされます (または、コンパクト オーバーレイ用に最適化されたカスタム タイトル バーを提供することもできます)。

public MainWindow()
{
    this.InitializeComponent();

    m_AppWindow = GetAppWindowForCurrentWindow();
    m_AppWindow.Changed += AppWindow_Changed;
}

private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
    // Check to see if customization is supported.
    // Currently only supported on Windows 11.
    if (args.DidPresenterChange
        && AppWindowTitleBar.IsCustomizationSupported())
    {
        switch (sender.Presenter.Kind)
        {
            case AppWindowPresenterKind.CompactOverlay:
                // Compact overlay - hide custom title bar
                // and use the default system title bar instead.
                AppTitleBar.Visibility = Visibility.Collapsed;
                sender.TitleBar.ResetToDefault();
                break;

            case AppWindowPresenterKind.FullScreen:
                // Full screen - hide the custom title bar
                // and the default system title bar.
                AppTitleBar.Visibility = Visibility.Collapsed;
                sender.TitleBar.ExtendsContentIntoTitleBar = true;
                break;

            case AppWindowPresenterKind.Overlapped:
                // Normal - hide the system title bar
                // and use the custom title bar instead.
                AppTitleBar.Visibility = Visibility.Visible;
                sender.TitleBar.ExtendsContentIntoTitleBar = true;
                SetDragRegionForCustomTitleBar(sender);
                break;

            default:
                // Use the default system title bar.
                sender.TitleBar.ResetToDefault();
                break;
        }
    }
}

Note

全画面表示 モードと コンパクト オーバーレイ モードは、アプリでサポートされている場合にのみ入力できます。 詳細については、 アプリ ウィンドウFullScreenPresenterCompactOverlayPresenter の管理に関するページを参照してください。

推奨と非推奨

  • ウィンドウがアクティブまたは非アクティブであるときには、それをわかりやすく示してください。 少なくとも、タイトル バーのテキスト、アイコン、ボタンの色を変更してください。
  • アプリ キャンバスの上端に沿ってドラッグ領域を定義します。 システム タイトル バーの配置に合わせると、ユーザーから見つけやすくなります。
  • アプリのキャンバス上のビジュアル タイトル バー (存在する場合) に一致するドラッグ領域を定義します。

全面的なカスタマイズの例

この例では、「完全なカスタマイズ」セクションで説明されているすべてのコードを示します。

(Windows 11のみ。詳細については、プラットフォーム オプションを参照してください)。

<Window
    x:Class="WASDK_ExtendedTitleBar.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WASDK_ExtendedTitleBar"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid x:Name="AppTitleBar"  
      Height="48">
            <Grid.ColumnDefinitions>
                <ColumnDefinition x:Name="LeftPaddingColumn" Width="0"/>
                <ColumnDefinition x:Name="IconColumn" Width="Auto"/>
                <ColumnDefinition x:Name="TitleColumn" Width="Auto"/>
                <ColumnDefinition x:Name="LeftDragColumn" Width="*"/>
                <ColumnDefinition x:Name="SearchColumn" Width="Auto"/>
                <ColumnDefinition x:Name="RightDragColumn" Width="*"/>
                <ColumnDefinition x:Name="RightPaddingColumn" Width="0"/>
            </Grid.ColumnDefinitions>
            <Image x:Name="TitleBarIcon" Source="/Images/WindowIcon.png"
           Grid.Column="1"
           Width="16" Height="16"
           Margin="8,0,0,0"/>
            <TextBlock x:Name="TitleTextBlock" 
               Text="App title" 
               Style="{StaticResource CaptionTextBlockStyle}"
               Grid.Column="2"
               VerticalAlignment="Center"
               Margin="4,0,0,0"/>
            <AutoSuggestBox Grid.Column="4" QueryIcon="Find"
                    PlaceholderText="Search"
                    VerticalAlignment="Center"
                    Width="260" Margin="4,0"/>
        </Grid>

        <NavigationView Grid.Row="1"
                        IsBackButtonVisible="Collapsed" 
                        IsSettingsVisible="False">
            <StackPanel>
                <TextBlock Text="Content" 
                           Style="{ThemeResource TitleTextBlockStyle}"
                           Margin="32,0,0,0"/>
                <StackPanel Grid.Row="1" VerticalAlignment="Center">
                    <Button Margin="4" x:Name="CompactoverlaytBtn"
                            Content="Enter CompactOverlay"
                            Click="SwitchPresenter"/>
                    <Button Margin="4" x:Name="FullscreenBtn" 
                            Content="Enter FullScreen"
                            Click="SwitchPresenter"/>
                    <Button Margin="4" x:Name="OverlappedBtn"
                            Content="Revert to default (Overlapped)"
                            Click="SwitchPresenter"/>
                </StackPanel>
            </StackPanel>
        </NavigationView>
    </Grid>
</Window>
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using WinRT.Interop;

namespace WASDK_ExtendedTitleBar
{
    public sealed partial class MainWindow : Window
    {
        private AppWindow m_AppWindow;

        public MainWindow()
        {
            this.InitializeComponent();

            m_AppWindow = GetAppWindowForCurrentWindow();
            m_AppWindow.Changed += AppWindow_Changed;

            // Check to see if customization is supported.
            // Currently only supported on Windows 11.
            if (AppWindowTitleBar.IsCustomizationSupported())
            {
                var titleBar = m_AppWindow.TitleBar;
                titleBar.ExtendsContentIntoTitleBar = true;
                AppTitleBar.Loaded += AppTitleBar_Loaded;
                AppTitleBar.SizeChanged += AppTitleBar_SizeChanged;
            }
            else
            {
                // Title bar customization using these APIs is currently
                // supported only on Windows 11. In other cases, hide
                // the custom title bar element.
                AppTitleBar.Visibility = Visibility.Collapsed;

                // Show alternative UI for any functionality in
                // the title bar, such as search.
            }

        }

        private void AppTitleBar_Loaded(object sender, RoutedEventArgs e)
        {
            if (AppWindowTitleBar.IsCustomizationSupported())
            {
                SetDragRegionForCustomTitleBar(m_AppWindow);
            }
        }

        private void AppTitleBar_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (AppWindowTitleBar.IsCustomizationSupported()
                && m_AppWindow.TitleBar.ExtendsContentIntoTitleBar)
            {
                // Update drag region if the size of the title bar changes.
                SetDragRegionForCustomTitleBar(m_AppWindow);
            }
        }

        private AppWindow GetAppWindowForCurrentWindow()
        {
            IntPtr hWnd = WindowNative.GetWindowHandle(this);
            WindowId wndId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
            return AppWindow.GetFromWindowId(wndId);
        }

        [DllImport("Shcore.dll", SetLastError = true)]
        internal static extern int GetDpiForMonitor(IntPtr hmonitor, Monitor_DPI_Type dpiType, out uint dpiX, out uint dpiY);

        internal enum Monitor_DPI_Type : int
        {
            MDT_Effective_DPI = 0,
            MDT_Angular_DPI = 1,
            MDT_Raw_DPI = 2,
            MDT_Default = MDT_Effective_DPI
        }

        private double GetScaleAdjustment()
        {
            IntPtr hWnd = WindowNative.GetWindowHandle(this);
            WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
            DisplayArea displayArea = DisplayArea.GetFromWindowId(wndId, DisplayAreaFallback.Primary);
            IntPtr hMonitor = Win32Interop.GetMonitorFromDisplayId(displayArea.DisplayId);

            // Get DPI.
            int result = GetDpiForMonitor(hMonitor, Monitor_DPI_Type.MDT_Default, out uint dpiX, out uint _);
            if (result != 0)
            {
                throw new Exception("Could not get DPI for monitor.");
            }

            uint scaleFactorPercent = (uint)(((long)dpiX * 100 + (96 >> 1)) / 96);
            return scaleFactorPercent / 100.0;
        }

        private void SetDragRegionForCustomTitleBar(AppWindow appWindow)
        {
            if (AppWindowTitleBar.IsCustomizationSupported()
                && appWindow.TitleBar.ExtendsContentIntoTitleBar)
            {
                double scaleAdjustment = GetScaleAdjustment();

                RightPaddingColumn.Width = new GridLength(appWindow.TitleBar.RightInset / scaleAdjustment);
                LeftPaddingColumn.Width = new GridLength(appWindow.TitleBar.LeftInset / scaleAdjustment);

                List<Windows.Graphics.RectInt32> dragRectsList = new();

                Windows.Graphics.RectInt32 dragRectL;
                dragRectL.X = (int)((LeftPaddingColumn.ActualWidth) * scaleAdjustment);
                dragRectL.Y = 0;
                dragRectL.Height = (int)(AppTitleBar.ActualHeight * scaleAdjustment);
                dragRectL.Width = (int)((IconColumn.ActualWidth
                                        + TitleColumn.ActualWidth
                                        + LeftDragColumn.ActualWidth) * scaleAdjustment);
                dragRectsList.Add(dragRectL);

                Windows.Graphics.RectInt32 dragRectR;
                dragRectR.X = (int)((LeftPaddingColumn.ActualWidth
                                    + IconColumn.ActualWidth
                                    + TitleTextBlock.ActualWidth
                                    + LeftDragColumn.ActualWidth
                                    + SearchColumn.ActualWidth) * scaleAdjustment);
                dragRectR.Y = 0;
                dragRectR.Height = (int)(AppTitleBar.ActualHeight * scaleAdjustment);
                dragRectR.Width = (int)(RightDragColumn.ActualWidth * scaleAdjustment);
                dragRectsList.Add(dragRectR);

                Windows.Graphics.RectInt32[] dragRects = dragRectsList.ToArray();

                appWindow.TitleBar.SetDragRectangles(dragRects);
            }
        }

        private void AppWindow_Changed(AppWindow sender, AppWindowChangedEventArgs args)
        {
            if (args.DidPresenterChange
                && AppWindowTitleBar.IsCustomizationSupported())
            {
                switch (sender.Presenter.Kind)
                {
                    case AppWindowPresenterKind.CompactOverlay:
                        // Compact overlay - hide custom title bar
                        // and use the default system title bar instead.
                        AppTitleBar.Visibility = Visibility.Collapsed;
                        sender.TitleBar.ResetToDefault();
                        break;

                    case AppWindowPresenterKind.FullScreen:
                        // Full screen - hide the custom title bar
                        // and the default system title bar.
                        AppTitleBar.Visibility = Visibility.Collapsed;
                        sender.TitleBar.ExtendsContentIntoTitleBar = true;
                        break;

                    case AppWindowPresenterKind.Overlapped:
                        // Normal - hide the system title bar
                        // and use the custom title bar instead.
                        AppTitleBar.Visibility = Visibility.Visible;
                        sender.TitleBar.ExtendsContentIntoTitleBar = true;
                        SetDragRegionForCustomTitleBar(sender);
                        break;

                    default:
                        // Use the default system title bar.
                        sender.TitleBar.ResetToDefault();
                        break;
                }
            }
        }

        private void SwitchPresenter(object sender, RoutedEventArgs e)
        {
            if (m_AppWindow != null)
            {
                AppWindowPresenterKind newPresenterKind;
                switch ((sender as Button).Name)
                {
                    case "CompactoverlaytBtn":
                        newPresenterKind = AppWindowPresenterKind.CompactOverlay;
                        break;

                    case "FullscreenBtn":
                        newPresenterKind = AppWindowPresenterKind.FullScreen;
                        break;

                    case "OverlappedBtn":
                        newPresenterKind = AppWindowPresenterKind.Overlapped;
                        break;

                    default:
                        newPresenterKind = AppWindowPresenterKind.Default;
                        break;
                }

                // If the same presenter button was pressed as the
                // mode we're in, toggle the window back to Default.
                if (newPresenterKind == m_AppWindow.Presenter.Kind)
                {
                    m_AppWindow.SetPresenter(AppWindowPresenterKind.Default);
                }
                else
                {
                    // Else request a presenter of the selected kind
                    // to be created and applied to the window.
                    m_AppWindow.SetPresenter(newPresenterKind);
                }
            }
        }
    }
}