single.php

C# WinUI3 の[TabView]左側にシステムメニューを表示する手順

C# WinUI 3アプリを作っていく途中で、調べたことを忘録的に投稿します。今回はWinUI3プロジェクトで、Xamlに追加した[TabView]コントロールのタブの左側のエリアにシステムメニューを表示させる手順です。

メモ帳のタブ左側部分

今回、やりたいことは[TabView]コントロールの左側部分にWindowsのシステムメニューを表示です。

具体的にはWindows11でタブ化された「メモ帳」のように、左上アイコンを右クリックした際に、システムメニュー([移動やサイズ変更]などがポップアップするメニュー)を表示させます。

WinUI3の[ExtendsContentIntoTitleBar]プロパティでタイトルバーをカスタマイズした際に、システムメニューを表示したい場合に有効です。

カスタムスタイルを設定

今回は、[ExtendsContentIntoTitleBar]を有効にした際にタイトルバーが非表示になりウィンドウをドラッグさせるための手段が無くなります。

そのため[TitleBar]クラスには[SetDragRectangles]メソッドがあり、マウスでドラッグする領域を設定できます。

この[SetDragRectangles]メソッドで指定したエリアは[タイトルバー]と同じ動作をするため、右クリックするとシステムメニューが表示されます。

具体的には、次の手順で取得します。

1. Xaml内の[TabView]コントロール内に[TabStripHeader]と[TabStripFooter]を追加します。

<Grid>
  <TabView Name="tab_main" HorizontalAlignment="Stretch"
    AddTabButtonClick="TabView_AddTabButtonClick"
    TabCloseRequested="TabView_TabCloseRequested">
    <TabView.TabStripHeader>
      <FontIcon Name="Home_Icon" Glyph="&#xE80F;" Margin="12,8,0,0"/>
    </TabView.TabStripHeader>
    <TabView.TabStripFooter>
      <Grid/>
    </TabView.TabStripFooter>
  </TabView>
</Grid>

[TabStripHeader]は追加されるタブの左側[TabStripFooter]はタブの右側に配置される余白のようなパーツです。

詳しい内容は[TabView(タブ ビュー)]をご覧ください。

2. 作業を保存して実行します。

タブの左側([TabStripHeader])にアイコンが表示されます。この時点ではマウスの右クリックしてもシステムメニューは表示されません。

3.[TabStripHeader]と[TabStripFooter]に[Grid]コントロールを追加します。(場所が分かりやすいように[Background]プロパティを設定しています)

<Grid>
  <TabView Name="tab_main" HorizontalAlignment="Stretch"
    AddTabButtonClick="TabView_AddTabButtonClick"
    TabCloseRequested="TabView_TabCloseRequested">
    <TabView.TabStripHeader>
      <Grid x:Name="LeftPaddingInset" Background="Red">
        <FontIcon Name="Home_Icon" Glyph="&#xE80F;" Margin="12,8,0,0"/>
      </Grid>
    </TabView.TabStripHeader>
    <TabView.TabStripFooter>
      <Grid x:Name="RightPaddingInset" Background="Blue"/>
    </TabView.TabStripFooter>
  </TabView>
</Grid>

4. 作業を保存して実行すると[TabStripHeader](赤色部分)と[TabStripFooter](青色部分)がタブの両端に表示されます。

この部分をドラッグ可能にするエリアとして[SetDragRectangles]メソッドで指定します。

5. ドラッグ可能なエリアを設定するコードを追加します。

タブ左側の[TabStripHeader](赤色部分)だけであれば、計算は必要ありませんが右側の[TabStripFooter](青色部分)はウィンドウのサイズ変更で横幅が変更されるのでイベントで新しい領域を設定しています。

また、本来は画面右上の[閉じる]や[最小化|最大化]操作を行うボタンのサイズ計算も必要ですが、今回は固定値([DragRegionMinWidth])を使っています。

private Microsoft.UI.Windowing.AppWindow m_AppWindow;

public TabViewStyle()
{
  this.InitializeComponent();

  IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
  Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
  m_AppWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);

  this.ExtendsContentIntoTitleBar = true;
  tab_main.TabItems.Add(CreateTabItem(tab_main.TabItems.Count));

  tab_main.SizeChanged += (s, e) => UpdateDragRectangles();
  RightPaddingInset.SizeChanged += (s, e) => UpdateDragRectangles();
}

private const int DragRegionMinWidth = 48;
private void UpdateDragRectangles()
{
  LeftPaddingInset.MinWidth = m_AppWindow.TitleBar.LeftInset;
  RightPaddingInset.MinWidth = m_AppWindow.TitleBar.RightInset +  DragRegionMinWidth;

  var dragRectLeft = new RectInt32
  {
    X = 0,
    Y = 0,
    Height = (int)tab_main.ActualHeight,
    Width = (int)LeftPaddingInset.ActualWidth
  };

  var dragRectRight = new RectInt32
  {
    X = (int)(tab_main.ActualWidth - RightPaddingInset.ActualWidth),
    Y = 0,
    Height = (int)tab_main.ActualHeight,
    Width = (int)(RightPaddingInset.ActualWidth - m_AppWindow.TitleBar.RightInset + DragRegionMinWidth)
  };

  m_AppWindow.TitleBar.SetDragRectangles(new[] { dragRectLeft, dragRectRight });
}

[TabStripHeader](赤色部分)だけであれば[dragRectLeft]だけを設定します。

6. 作業を保存して実行すると[赤色]と[青色]の部分で右クリックするとシステムメニューがポップアップ表示されます。

まとめ

今回は、WinUI3プロジェクトで、Xamlに追加した[TabView]コントロールのタブ左側にアイコンを表示して右クリックでシステムメニューを表示する手順を紹介しました。

[TabView]コントロールには左右に[TabStripHeader]と[TabStripFooter]と呼ばれるパーツが用意されています。

[TabStripHeader]にアイコンを表示して、[SetDragRectangles]メソッドでドラッグ可能な矩形として設定することで、右クリックでシステムメニューが表示されます。

WinUI 3アプリで[TabView]コントロールで追加したタブの左側にシステムメニューを表示したい人の参考になれば幸いです。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です