【WPF】超簡単!ウィンドウ枠の非表示+独自タイトルバー+リサイズ+ドラッグの実装方法(WindowChromeクラス)

当ページのリンクには広告が含まれています。

Material Design in XAML ToolKit を使ってモダンなデザイン画面を作る際、ウィンドウのタイトルバーも合わせてモダンにしたくなりませんか?

そこで真っ先に思いつくのが、MahApps.Metroです。でも、これを使うとMaterial Designのデザインが影響を受けてしまい、Material Designの美しさが損なわれてしまいます。

そこで調べたところ、Microsoftが提供するWindowChromeを使えば簡単に実現できることが分かりました。

本記事では、すぐに使えるよう、「リサイズ」、「ドラッグ移動」、「拡大」、「縮小」、「閉じる」を実装した MainWindowのXAMLとC#のサンプルを紹介しています。

Material Design in XAML ToolKitを使う人も、使わない人のどちらも同じ記述で実装できるので、記述非参考にしてください。

目次

WindowChromeとは

WindowChromeとは、WPF (Windows Presentation Foundation) アプリケーションでウィンドウの外観をカスタマイズするためのクラスの名称です。

このクラスを使用することで、ウィンドウのタイトルバーやボーダーのデザインを自分好みに変更できます。具体的には、ウィンドウのクローム部分(ウィンドウのフレームやボタン)をカスタマイズする機能を提供します。

  • ウィンドウのフレームのカスタマイズ
    標準的なウィンドウフレームを削除し、自分のデザインを適用することができます。
  • タイトルバーのカスタマイズ
    カスタムタイトルバーを作成し、そこにボタンや他のコントロールを配置することができます。
  • ウィンドウのリサイズエリアのカスタマイズ
    ウィンドウのリサイズエリアをカスタマイズすることができ、ユーザーがウィンドウをドラッグしてサイズを変更する方法を制御できます。

詳細はMicrosoftの「WindowChrome クラス」をご確認下さい。

今回紹介するサンプル画面

本記事で紹介するサンプルコードを実行すると、上記のシンプルな画面が作成できます。
これは独自のタイトルバーに「縮小」「拡大」「閉じる」ボタンを配置し、かつ画面いっぱいにテキストボックスを張り付けたウィンドウです。

WindowChromeの組み込み

次の3行を追加することで、タイトルバーとウィンドウ枠が非表示となり、かつリサイズとドラッグ移動が可能な真っ白なウィンドウが作成できます。

   <WindowChrome.WindowChrome>
        <WindowChrome CaptionHeight="30" CornerRadius="0" GlassFrameThickness="0" ResizeBorderThickness="5"/>
    </WindowChrome.WindowChrome>

追加する場所は下記の通りです。

CaptionHeightはウィンドウをドラッグ移動するための検知範囲を指定するもので、ウィンドウ上端からのドット数で指定します。上記の例では30を指定していますので、ウインドウ上端から30ドットの範囲でドラッグ移動を受け付けてくれます。

次は、この真っ白なウィンドウに対して、独自のタイトルバーと「最大」「最小」「閉じる」ボタンを実装します。

独自タイトルバーとイベントの実装

独自のタイトルバーと言っても、単にGridやDockPanelなどのコントロールを張り付けて、そこにタイトルと「最大」「最小」「閉じる」のボタンを配置し、イベント処理を記述するだけです。

但し、単にボタンを張り付けただけではクリックを受け付けてくれません。これはCaptionHeightで指定したドラッグ受付領域に、クリックイベントが横取りしてしまうからです。

嬉しいことに、CaptionHeightと重なるエリアに配置したボタンに下記の1行を記述してやることで、クリックイベントを横取りされなくなります。

WindowChrome.IsHitTestVisibleInChrome="True"

下記サンプルでは、独自のタイトルバーをDockPanelを使って実現しています。

<Window x:Class="WindowTitleDemo.MainWindow"
        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"
        xmlns:local="clr-namespace:WindowTitleDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <WindowChrome.WindowChrome>
        <WindowChrome CaptionHeight="30" CornerRadius="0" GlassFrameThickness="0" ResizeBorderThickness="5"/>
    </WindowChrome.WindowChrome>
    <Grid>
        <DockPanel LastChildFill="True" >
            <DockPanel DockPanel.Dock="Top" Background="#3393DF" Height="30">
                <Label DockPanel.Dock="Left" VerticalContentAlignment="Center" Padding="10,0,0,0" Foreground="White" 
                       Content="WindowTitleDemo"/>
                <Button x:Name="uxWindowClose"
                          WindowChrome.IsHitTestVisibleInChrome="True"  
                          Foreground="White"
                          Background="Transparent"
                          BorderThickness="0"
                          Content="X"
                          Width="30"
                          Margin="0,0,10,0"
                          Click="uxWindowClose_Click"
                          VerticalAlignment="Center"
                          HorizontalAlignment="Right"
                          DockPanel.Dock="Right"
                          ToolTip="ウィンドウを閉じる">
                </Button>
                <Button x:Name="uxWindowMaximize" 
                          WindowChrome.IsHitTestVisibleInChrome="True"  
                        Foreground="White"
                          Background="Transparent"
                          BorderThickness="0"
                          Content="□"
                          Click="uxWindowMaximize_Click"
                          DockPanel.Dock="Right"
                          VerticalAlignment="Center"
                          HorizontalAlignment="Right"
                          ToolTip="ウィンドウサイズを最大化する" Cursor="Hand" >
                </Button>
                <Button x:Name="uxWindowMinimize"
                          WindowChrome.IsHitTestVisibleInChrome="True"  
                          Foreground="White"
                          Background="Transparent"
                          BorderThickness="0"
                          Content="-"
                          Width="30" 
                          Click="uxWindowMinimize_Click"
                          VerticalAlignment="Center"
                          DockPanel.Dock="Right"
                          HorizontalAlignment="Right"
                          ToolTip="ウィンドウサイズを最小化する">
                </Button>
            </DockPanel>
            // ここに画面デザインのためのコントロールを張り付けて下さい。
            <TextBox AcceptsReturn="True" Background="Lavender"></TextBox>
        </DockPanel>
    </Grid>
</Window>

下記サンプルは、上記XAMLに対応したC#側のイベント処理です。

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WindowTitleDemo
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// このクラスは MainWindow.xaml ファイルのコードビハインドであり、ユーザーの操作を処理します。
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// MainWindow クラスの新しいインスタンスを初期化します。
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
        }

        /// <summary>
        /// uxWindowClose ボタンの Click イベントを処理します。
        /// ウィンドウを閉じます。
        /// </summary>
        /// <param name="sender">イベントの発生元。</param>
        /// <param name="e">イベントデータを含む RoutedEventArgs インスタンス。</param>
        private void uxWindowClose_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// uxWindowMinimize ボタンの Click イベントを処理します。
        /// ウィンドウを最小化します。
        /// </summary>
        /// <param name="sender">イベントの発生元。</param>
        /// <param name="e">イベントデータを含む RoutedEventArgs インスタンス。</param>
        private void uxWindowMinimize_Click(object sender, RoutedEventArgs e)
        {
            this.WindowState = WindowState.Minimized;
        }

        /// <summary>
        /// uxWindowMaximize ボタンの Click イベントを処理します。
        /// ウィンドウの状態を最大化と通常の間で切り替えます。
        /// </summary>
        /// <param name="sender">イベントの発生元。</param>
        /// <param name="e">イベントデータを含む RoutedEventArgs インスタンス。</param>
        private void uxWindowMaximize_Click(object sender, RoutedEventArgs e)
        {
            this.WindowState = (this.WindowState == WindowState.Maximized) ? WindowState.Normal : WindowState.Maximized;
        }
    }
}

WindowChromeで設定可能なプロパティ一覧

WindowChrome の設定可能なプロパティを以下のテーブル形式でまとめました。

<WindowChrome.WindowChrome>
<WindowChrome CaptionHeight="30" CornerRadius="0" ResizeBorderThickness="5"/>
</WindowChrome.WindowChrome>

プロパティ説明
CaptionHeightdoubleウィンドウのタイトルバーの高さ(ピクセル単位)。
CornerRadiusCornerRadiusウィンドウの角の半径。円弧の曲率を指定します。
GlassFrameThicknessThicknessグラスフレーム(エアログラス)の厚さを指定します。
ResizeBorderThicknessThicknessウィンドウのリサイズボーダーの厚さ。
NonClientFrameEdgesNonClientFrameEdgesウィンドウのカスタム非クライアントフレームエッジを指定します。
UseAeroCaptionButtonsboolAeroスタイルのキャプションボタンを使用するかどうかを指定します。
IsHitTestVisibleInChromeboolウィンドウクローム内の要素がヒットテストに参加するかどうかを指定します。

まとめ

本記事では、WindowChrome使ったウインドウ枠の非表示、リサイズとドラッグによる移動、独自タイトルバーの実装方法について、具体的なサンプルコードを交えて紹介しました。

WindowChromeを活用することで、以下のポイントを簡単に実装できます。

  • ウィンドウフレームのカスタマイズ:標準のウィンドウフレームを排除し、自分好みのデザインを適用。
  • 独自タイトルバーの作成:自由にレイアウトできるGridやDockPanelを活用し、ウィンドウの「最小化」「最大化」「閉じる」ボタンを設置。
  • クリックイベントの対応WindowChrome.IsHitTestVisibleInChrome を利用することで、ボタンのクリックイベントを適切に処理。
  • リサイズとドラッグ移動ResizeBorderThicknessCaptionHeight で柔軟なサイズ変更とウィンドウ移動が可能。

これにより、アプリケーションの外観を大幅に向上させることができ、見栄えの良いアプリが作れるようになります。

MahApps.Metroを使うとMaterial Design in XAML ToolKit のデザインが影響を受ける問題も解決します。
WindowChromeはとてもシンプルなコードで実装可能なため、WPFプロジェクトのデザインを強化したい方はぜひ試してみてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次