WPFでウィンドウを独自に作成したい場合は、自分でWindowのControlTemplateをゴリゴリ作るのも楽しいのですが、もう少し簡単に実現したい時、WindowChromeを使用するといいと思います。
WindowChromeとは?
WindowChromeは、Windowの非クライアント領域にWindowのContentを拡張するための仕組みです。
MDSN : WindowChrome クラス (System.Windows.Shell)
通常、Windowにはタイトルバーや閉じるボタンが配置されている非クライアント領域と、その内側のクライアント領域があります。
Windowにコントロールを配置するときは、このクライアント領域に配置しますよね。
で、WindowChromeはこのクライアント領域を拡大してくれる仕組みを持っています。
説明ばかりではわかりにくいので実際に作ってみましょう。
WindowChromeを使う
まずは通常のWindowを用意
<Window x:Name="window" x:Class="WindowChromeSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> </Grid.RowDefinitions> <DockPanel> <TextBlock Text="{Binding Title, ElementName=window, Mode=OneWay}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="6,3,12,3" FontSize="14.667" /> <Button Content="✕" Width="24" Height="24" HorizontalAlignment="Right" Background="Red" BorderThickness="0" Foreground="White"/> </DockPanel> </Grid> </Window>
これを実行すると以下の様なウィンドウが表示されます。
このウィンドウにStyleを追加し、プロパティ"WindowChrome.WindowChrome"を設定します。
< Generic.xaml >
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib"> <!-- リソース ディクショナリのエントリはここで定義します。--> <System:Double x:Key="CaptionHeight">26</System:Double> <Style TargetType="{x:Type Window}" x:Key="DefaultWindowStyle"> <Setter Property="WindowChrome.WindowChrome"> <Setter.Value> <WindowChrome CornerRadius="3" GlassFrameThickness="1" ResizeBorderThickness="8" UseAeroCaptionButtons="False" CaptionHeight="{DynamicResource CaptionHeight}" /> </Setter.Value> </Setter> <Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="UseLayoutRounding" Value="True"/> <Setter Property="Background" Value="#FF494949"/> <Setter Property="BorderBrush" Value="#FF14A9FF"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="Foreground" Value="White"/> </Style> </ResourceDictionary>
< MainWindow.xaml >
<Window x:Name="window" x:Class="WindowChromeSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Style="{DynamicResource DefaultWindowStyle}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition/> </Grid.RowDefinitions> <DockPanel> <TextBlock Text="{Binding Title, ElementName=window, Mode=OneWay}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="6,3,12,3" FontSize="14.667" /> <Button Content="✕" Width="24" Height="24" HorizontalAlignment="Right" Background="Red" BorderThickness="0" Foreground="White" WindowChrome.IsHitTestVisibleInChrome="True"/> </DockPanel> </Grid> </Window>
これを実行した結果がこちら
あとはタイトルバーに最大化ボタンや最小化ボタンを配置すると独自ウィンドウの完成です。
仕事で時々閉じるボタンを非表示にしてくれと言われることがあるので、そんな時は便利そうですね。
CaptionHeight を設定しておけばウィンドウのドラッグ移動や最大化もできます。
また、これを利用するとWindows10ライクなWindowも作成できそうです。
ちなみに、キャプションエリアにコントロールを配置した場合、そのままではコントロールをクリックすることはできません。
今回の場合、WindowChrome.CaptionHeight を26に設定しています。
この問題を解決するには、キャプションエリアに配置したコントロールにWindowChromeの添付プロパティ"WindowChrome.IsHitTestVisibleInChrome"にtrueを設定することで対応できます。
上記の場合、
です。
WindowChromeの問題点
一見便利そうなWindowChromeにも問題点はあります。
・最大化した時にデスクトップのクライアント領域を超える。
・SizeToContent=WidthAndHeight にすると現れる謎の黒い領域
次回はこの辺りの対策を紹介したいと思います。
サンプルはこちらから