single.php

C# WinUI3 でウィンドウをドラッグできる場所をカスタマイズする方法

C# WinUI 3アプリを作っていく途中で、調べたことを忘録的に投稿します。今回はWinUI3プロジェクトで、通常はタイトルバーを設定されているウィンドウを移動するためにドラッグする場所を、別の場所に設定する場合の対処法です。

ドラッグ可能な要素を指定

WinUI3では、要素などを指定してウィンドウのドラッグ可能な矩形を指定するために[AppWindow.TitleBar.SetDragRectangles]メソッドが用意されてます。

例えば次のコードのようにGridレイアウトで左右に分割した[StackPanel]要素を作ります。

<Grid Name="MainGrid" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" SizeChanged="MainGrid_SizeChanged">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="0.5*"></ColumnDefinition>
    <ColumnDefinition Width="0.5*"></ColumnDefinition>
  </Grid.ColumnDefinitions>
  <StackPanel Name="LeftPanel" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Red">
    <TextBlock Margin="0,128,0,0" Text="ドラッグ可能" VerticalAlignment="Center" HorizontalAlignment="Center" />
  </StackPanel>
  <StackPanel Name="RightPanel" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <TextBlock Margin="0,64,0,0" Text="ドラッグ不可" VerticalAlignment="Center" HorizontalAlignment="Center" />
  </StackPanel>
</Grid>

実行すると、こんな感じで左右に分割された画面が表示されます。

クラスの初期化時に次のコードを追加します。

public CustomDragRegion()
{
  this.InitializeComponent();
  this.ExtendsContentIntoTitleBar = true;
  this.SetTitleBar(LeftPanel);
}

このコードを実行すると、指定した[StackPanel Name=”LeftPanel”](左側の赤い部分)をマウスでドラックするとウィンドウが移動します。

ドラッグ可能な場所を複数指定

その他にもWinUI3には[AppWindow.TitleBar.SetDragRectangles]メソッドが用意されていて、Rectクラス配列を使って複数のドラッグ可能な場所を指定できます。

例えば、先ほどのXamlに追加で[StackPanel]を追加します。

<Grid Name="MainGrid" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" SizeChanged="MainGrid_SizeChanged">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="0.5*"></ColumnDefinition>
    <ColumnDefinition Width="0.5*"></ColumnDefinition>
  </Grid.ColumnDefinitions>
  <StackPanel Name="LeftPanel" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Red">
    <TextBlock Margin="0,128,0,0" Text="ドラッグ可能" VerticalAlignment="Center" HorizontalAlignment="Center" />
  </StackPanel>
  <StackPanel Name="RightPanel" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <TextBlock Margin="0,64,0,0" Text="ドラッグ不可" VerticalAlignment="Center" HorizontalAlignment="Center" />
    <StackPanel Name="RightInPanel" Margin="0,64,0,0" Width="100" Height="100" Background="Red">
      <TextBlock Text="ドラッグ可能" VerticalAlignment="Center" HorizontalAlignment="Center" />
    </StackPanel>
  </StackPanel>
</Grid>

関数を1つ追加して[StackPanel]の場所をRectクラスを使って設定を行います。

public CustomDragRegion()
{
  this.InitializeComponent();
  this.ExtendsContentIntoTitleBar = true;
  this.SetTitleBar(LeftPanel);
  UpdateDragRectangles();
}

private void UpdateDragRectangles()
{
  double dpiRasio = GetDpi() / 96;
  Rect rect = new Rect(0.0, 0.0, RightInPanel.ActualWidth, RightInPanel.ActualHeight);
  if (RightInPanel.ActualWidth == 0)
  {
    return;
  }

  Microsoft.UI.Xaml.Media.GeneralTransform transformPanel = RightInPanel.TransformToVisual(null);
  rect = transformPanel.TransformBounds(rect);
  Rect rect2 = new Rect(rect.Left * dpiRasio, rect.Top * dpiRasio, rect.Width * dpiRasio, rect.Height * dpiRasio);

  var dragRect = new RectInt32
  {
    X = (int)(rect.Left * dpiRasio),
    Y = (int)(rect.Top * dpiRasio),
    Height = (int)(rect.Height * dpiRasio),
    Width = (int)(rect.Width * dpiRasio)
  };

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

  appWindow.TitleBar.SetDragRectangles(new[] { dragRect });
}

実行すると、こんな感じでタイトルバーに追加して2つの場所を使ってウィンドウの移動が可能になります。

まとめ

今回はWinUI3プロジェクトで、通常はタイトルバーを設定されているウィンドウを移動するためにドラッグする場所を、別の場所に設定する場合の対処法について紹介しました。

WinUI3では、マウスポインターでウィンドウの移動を可能にする場所を指定するためにタイトルバーに[SetTitleBar]プロパティと[SetDragRectangles]メソッドが用意されています。

また、[SetDragRectangles]メソッドを利用すると複数の矩形をドラッグできる場所として設定が可能です。

WinUI 3アプリのウィンドウを移動するための場所をタイトルバー以外に設定したい人の参考になれば幸いです。

スポンサーリンク

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

コメントを残す

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