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

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

タイトル バーを示す Windows アプリ

アプリの タイトル バー 、許容できるタイトル バー領域のコンテンツ、推奨される 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 のバージョンやWindows アプリ SDKのバージョンによって異なります。 この表では、詳細について説明します。

カスタマイズ オプション Windows 10 Windows 11
簡単なカスタマイズ 部分的に、Windows アプリ SDK 1.2 以降 (色のカスタマイズはサポートされていません) はい、すべてのバージョンのWindows アプリ SDK
全面的なカスタマイズ はい(Windows アプリ SDK 1.2 以降) はい、すべてのバージョンのWindows アプリ SDK

Windows アプリ SDK 1.2 以降、Windows 10でサポートされている API の詳細については、「ウィンドウ」セクションの「Windows アプリ SDKリリース ノート」ページを参照してください。

アプリが他のバージョンの Windows でクラッシュしないようにするには、これらの API を呼び出す前に、コードで AppWindowTitleBar.IsCustomizationSupported をチェックすることをお勧めします。

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

AppWindow を使用する方法

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

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

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

シンプル

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

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

[完全]

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

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

簡単なカスタマイズ

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

(Windows アプリ SDK 1.2 以降のWindows 10で部分的にサポートされ、Windows 11で完全にサポートされています。詳細については、「プラットフォーム オプション」を参照してください)。

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

タイトル

既定では、タイトル バーにはアプリの種類がウィンドウ タイトルとして表示されます ("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.
    // The method returns true on Windows 10 since Windows App SDK 1.2, and on all versions of
    // Windows App SDK on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported())
    {
        if (m_AppWindow is null)
        {
            m_AppWindow = GetAppWindowForCurrentWindow();
        }
        var titleBar = m_AppWindow.TitleBar;

        // Set active window colors
        // Note: No effect when app is running on Windows 10 since color customization is not
        // supported.
        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
        // Note: No effect when app is running on Windows 10 since color customization is not
        // supported.
        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 などのアイコン関数の 1 つからアイコン (HICON) へのハンドルが既にある場合は、GetIconIdFromIcon 相互運用 API を使用して IconId を取得できます。 その後、 を IconIdSetIcon(IconId) メソッドに渡して、ウィンドウ アイコンを設定できます。

    m_AppWindow.SetIcon(iconId));
    

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

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

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

全面的なカスタマイズ

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

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

ヒント

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

(Windows アプリ SDK 1.2 以降Windows 10でサポートされ、Windows 11で完全にサポートされています。詳細については、「プラットフォーム オプション」を参照してください)。

この例では、 AppWindowTitleBar を取得し、 ExtendsContentIntoTitleBar プロパティを に設定する true方法を示します。

重要

タイトル バーのカスタマイズ API は、アプリが実行される可能性がある Windows のすべてのバージョンではサポートされていないため、これらの API を呼び出す前に、必ずコードで AppWindowTitleBar.IsCustomizationSupported をチェックしてください。 タイトル バーのカスタマイズがサポートされていない場合は、通常、 を に設定 Visibility してカスタム タイトル バー UI を 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.
    // The method returns true on Windows 10 since Windows App SDK 1.2, and on all versions of
    // Windows App SDK on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported())
    {
        var titleBar = m_AppWindow.TitleBar;
        // Hide default title bar.
        titleBar.ExtendsContentIntoTitleBar = true;
    }
    else
    {
        // In the case that title bar customization is not supported, 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 アプリ SDK 1.2 以降Windows 10でサポートされ、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 、後で示すコードで設定されます。 コードと説明については、「システム キャプション ボタン」セクションを参照してください。

対話型コンテンツ

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

タイトル バーに検索ボックスがある Windows アプリ

(Windows アプリ SDK 1.2 以降Windows 10でサポートされ、Windows 11で完全にサポートされています。詳細については、「プラットフォーム オプション」を参照してください)。

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

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

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

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

  • グリッドの AppTitleBar 高さを 48 に設定して、対話型コンテンツの タイトル バー のデザイン ガイダンスに従います。
  • ドラッグ四角形の計算を簡単にするには、レイアウトに複数の名前付き列を含む を使用 Grid します。
  • MainWindow コンストラクターで を にtrue設定ExtendsContentIntoTitleBarします。 後で呼び出されるコードで設定すると、既定のシステム タイトル バーが最初に表示され、次に非表示になることがあります。
  • 要素が読み込まれた後にドラッグ領域を計算する最初の呼び出しを AppTitleBar 行います (AppTitleBar_Loaded)。 それ以外の場合、計算に使用される要素が正しい値を持つ保証はありません。
  • 要素のサイズAppTitleBar_SizeChanged () が変更された後にのみ、ドラッグ四角形の計算をAppTitleBar更新します。 ウィンドウ Changed イベントに依存している場合、イベントがサイズ変更される前に AppTitleBar 発生し、計算で正しくない値が使用される状況 (ウィンドウの最大化や最小化など) が発生します。
  • をチェックIsCustomizationSupportedした後にのみ を呼び出SetDragRectanglesしてExtendsContentIntoTitleBar、カスタム タイトル バーがサポートされ、使用されていることを確認します。
<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.
    // The method returns true on Windows 10 since Windows App SDK 1.2, and on all versions of
    // Windows App SDK on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported())
    {
        var titleBar = m_AppWindow.TitleBar;
        titleBar.ExtendsContentIntoTitleBar = true;
        AppTitleBar.Loaded += AppTitleBar_Loaded;
        AppTitleBar.SizeChanged += AppTitleBar_SizeChanged;
    }
    else
    {
        // In the case that title bar customization is not supported, 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.
    // The method returns true on Windows 10 since Windows App SDK 1.2, and on all versions of
    // Windows App SDK on Windows 11.
    if (AppWindowTitleBar.IsCustomizationSupported())
    {
        SetDragRegionForCustomTitleBar(m_AppWindow);
    }
}

private void AppTitleBar_SizeChanged(object sender, SizeChangedEventArgs e)
{
    // Check to see if customization is supported.
    // The method returns true on Windows 10 since Windows App SDK 1.2, and on all versions of
    // Windows App SDK 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.
    // The method returns true on Windows 10 since Windows App SDK 1.2, and on all versions of
    // Windows App SDK 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、および を使用する場合、RightInsetLeftInset表示スケールが 100% でない場合は、渡されたSetDragRectangles値を調整する必要があります。 この例では、表示スケール設定を scaleAdjustment 考慮する値を計算します。

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

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

ヒント

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

システム タイトル ボタン

(Windows アプリ SDK 1.2 以降Windows 10でサポートされ、Windows 11で完全にサポートされています。詳細については、「プラットフォーム オプション」を参照してください)。

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

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

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

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

キャプションコントロール領域の寸法と位置は AppWindowTitleBar クラスによって伝達されるため、タイトル バー UI のレイアウトで考慮できます。 両側の予約領域の幅は 、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);

重要

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

カスタム タイトル バーの背の高いタイトル バーのサポート

タイトル バーに検索ボックスや人物画像などの対話型コンテンツを追加する場合は、タイトル バーの高さを増やして、これらの要素のスペースを増やすことをお勧めします。 高いタイトル バーを使用すると、タッチ操作も簡単になります。 AppWindowTitleBar.PreferredHeightOption プロパティを使用すると、タイトル バーの高さを標準の高さ (既定値) から高い高さに増やすことができます。 タイトル バー モードを選択Tallすると、システムがクライアント領域にオーバーレイとして描画するキャプション ボタンは、グリフの最小/最大/閉が中央に配置された高さになります。 ドラッグ領域を指定していない場合は、ウィンドウの幅と、設定した値によって PreferredHeightOption 決定される高さを拡張するドラッグ領域が描画されます。

プロパティを有効にするには、AppWindowTitleBar.ExtendsContentIntoTitleBar プロパティを指定する必要がありますtruePreferredHeightOption。 に設定する前に を PreferredHeightOptiontrue設定ExtendsContentIntoTitlebarした場合、プロパティは に設定ExtendsContentIntoTitlebarされるまで自動的にtrue無視され、その時点で有効になります。

この例では、 プロパティを設定する方法を PreferredHeightOption 示します。

bool isTallTitleBar = true;

// A taller title bar is only supported when drawing a fully custom title bar
if (AppWindowTitleBar.IsCustomizationSupported() && m_AppWindow.TitleBar.ExtendsContentIntoTitleBar)
{
       if (isTallTitleBar)
       {
            // Choose a tall title bar to provide more room for interactive elements 
            // like search box or person picture controls.
            m_AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
       }
       else
       {
            _mainAppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Standard;
       }
       // Recalculate the drag region for the custom title bar 
       // if you explicitly defined new draggable areas.
       SetDragRegionForCustomTitleBar(_m_AppWindow);
}

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

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

(Windows アプリ SDK 1.2 以降Windows 10でサポートされ、Windows 11で完全にサポートされています。詳細については、「プラットフォーム オプション」を参照してください)。

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

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

リファレンス: Colors.TransparentColorHelper

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

ヒント

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

ウィンドウが非アクティブな場合にタイトル バーを暗くする

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

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

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

(Windows アプリ SDK 1.2 以降Windows 10でサポートされ、Windows 11で完全にサポートされています。詳細については、「プラットフォーム オプション」を参照してください)。

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

m_AppWindow.TitleBar.ResetToDefault();

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

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

(Windows アプリ SDK 1.2 以降Windows 10でサポートされ、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.
    // The method returns true on Windows 10 since Windows App SDK 1.2, and on all versions of
    // Windows App SDK 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

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

推奨と非推奨

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

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

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

(Windows アプリ SDK 1.2 以降Windows 10でサポートされ、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.
            // The method returns true on Windows 10 since Windows App SDK 1.2, and on all versions
            // of Windows App SDK on Windows 11.
            if (AppWindowTitleBar.IsCustomizationSupported())
            {
                var titleBar = m_AppWindow.TitleBar;
                titleBar.ExtendsContentIntoTitleBar = true;
                AppTitleBar.Loaded += AppTitleBar_Loaded;
                AppTitleBar.SizeChanged += AppTitleBar_SizeChanged;
            }
            else
            {
                // In the case that title bar customization is not supported, 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);
                }
            }
        }
    }
}