Zenn
🎗️

WinUI 3 タイトルバーにコントロールを載せる(Visual Studio のように)

に公開

はじめに

Windows App SDK 1.7 で新しい TitleBar コントロールが導入されたので、それも活用しながらタイトルバーをカスタマイズします。

例えば Visual Studio ではタイトルバーの中に

  • メニューバー
  • 検索ボタン
  • 背景色の異なるソリューション名表示

などがありますが、そういった感じのコントロールを載せるリッチなタイトルバーを作ります。

サンプルプログラムは GitHub に上げてあります。

突然ですが

TitleBar コントロールは残念ながらあまり使い物になりません。

  • Title Subtitle(タイトル文字列)が妙に下に配置される(Alignment 的なプロパティーは見当たらない)
  • Content(コントロールを載せられるところ)をマウスで掴んでウィンドウドラッグ(移動)できない
  • Content がセンタリング固定(左寄せにできない)
  • RightHeader が最小化・最大化ボタンとかぶる(ウィンドウサイズに余裕があるのに)

というような状況になっています。

例えば Visual Studio ではタイトルバーのソリューション名を掴んでウィンドウ移動できますが、TitleBar コントロールではこれができないので、ユーザーとしてはかなり戸惑うと思います。

スタイルや SetRegionRects() などを頑張ればいい感じになるのかもしれませんが、あまり頑張りたくありません。本稿執筆時点では WinUI 3 Gallery が Windows App SDK 1.6 ベースのままで、これが 1.7 ベースになれば扱いやすい情報も出てくるのかもしれません。

ただ、まったくダメかというとそうでもなくて、光るものも持っており、

  • システムメニュー(「元のサイズに戻す」など)を表示できる

というのが長所です。これまではタイトルバーをカスタマイズするとシステムメニューが表示されませんでした。

結論

システムメニューを TitleBar コントロールで表示し、それ以外を従来のやり方で配置するハイブリッド方式が現状ではお手軽です。

XAML は以下のようになります。

<Page
    x:Class="TestTitleBar.Views.MainWindows.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

  <RelativePanel >

    <!-- タイトルバー行:SetTitleBar() で指定するコントロール -->
    <RelativePanel Name="TitleLine" Height="32" RelativePanel.AlignLeftWithPanel="True" RelativePanel.AlignRightWithPanel="True" >

      <StackPanel Orientation="Horizontal" >

        <!-- タイトルバーコントロール:システムアイコン表示用としてのみ使用 -->
        <TitleBar Width="32" >
          <TitleBar.IconSource >
            <ImageIconSource ImageSource="/Assets/WindowIcon.ico" />
          </TitleBar.IconSource>
        </TitleBar>

        <!-- メニューバー -->
        <MenuBar VerticalAlignment="Center" >
          <MenuBarItem Title="ファイル(F)" AccessKey="F" >
            <MenuFlyoutItem Text="終了(Q)" AccessKey="Q" Command="{x:Bind ViewModel.NotImplementedClickedCommand}" />
          </MenuBarItem>
          (以降略)

TitleLine と名付けた RelativePanel がタイトルバー全体になります。

その中に新登場の TitleBar を配置しますが、IconSource のみを使用します。また、無駄に右側に空白ができるので Width も指定しています。

それ以外のコントロールは TitleBar を使わず、普段通りのコントロールを使って TitleLine 内に配置します。

タイトルバー全体をカスタムタイトルバーとして指定するコードビハインドは以下のようになります。

mainWindow.ExtendsContentIntoTitleBar = true;
FrameworkElement? customTitleBar = FindName("TitleLine") as FrameworkElement;
if (customTitleBar != null)
{
  mainWindow.SetTitleBar(customTitleBar);
}

SetTitleBar() で TitleLine をカスタムタイトルバーにしています。

これにより、

  • アイコンクリックでシステムメニュー表示
  • メニューバーなどを左寄せ
  • 背景色を変えたドキュメント名
  • ドキュメント名をマウスで掴んでウィンドウドラッグ(移動)

などが可能なカスタムタイトルバーになります。

なお、右寄せが貫通してしまうのは TitleBar と同様なので、右寄せのコントロールには Margin を指定して対処しています。

サンプルプログラム

サンプルプログラム(GitHub に上げてあります)を実行すると、カスタムタイトルバーが表示されます。

おわりに

Windows App SDK のバージョンアップにより、TitleBar のフル機能が問題なく使えるようになることを願っています。

確認環境

項目 環境
OS Windows 11 Pro 23H2
Visual Studio 2022 17.13.5
.NET 9.0
Template Studio for WinUI 5.5
WinUIEx 2.5.1
Windows App SDK 1.7.250310001 (1.7.0)

参考リンク

Discussion

ログインするとコメントできます