CustomScript

2014年11月30日日曜日

WPF勉強(7) VisualStudio2013みたいなスタイルのウィンドウを作る

  • .Net4.5
  • Win7


ウィンドウの見栄えをVisualStudio2013のようにします。

下記ページを参考に作成していますので、まずこちらをご一読ください

【grabacr.nét】WPF で Zune のようなウィンドウを作る
 http://grabacr.net/archives/480

使用するリソースは以下の2つです
WindowChrome
非クライアント領域のカスタマイズ
.Net4.5には標準で入っています

PresentationFramework.AeroLite
Windows8っぽいテーマ
参照に追加します。配布バイナリが動かない場合はプロパティの「ローカルコピー」をTrueにしてください

スタイル定義は以下の通りです。
AeroLiteテーマを適用し、システムボタン用にスタイルを幾つか追加定義しています。
<ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    
    <ResourceDictionary.MergedDictionaries>

        <!-- Theme: AeroLite -->
        <ResourceDictionary Source="/presentationframework.AeroLite;component/themes/aerolite.normalcolor.xaml" />

        <!-- Custom Styles -->
        <ResourceDictionary>
            <SolidColorBrush x:Key="WindowColor" Color="#FFD6DBE9"/>
            <SolidColorBrush x:Key="ClientColor" Color="#FF293955"/>

            <!-- System Buttons -->
            <Style x:Key="SystemButton" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
                <Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
                <Setter Property="Background" Value="{StaticResource WindowColor}" />
                <Setter Property="BorderBrush" Value="{StaticResource WindowColor}" />
                <Setter Property="IsTabStop" Value="False"/>
                <Setter Property="FontFamily" Value="Marlett" />
                <Setter Property="FontSize" Value="14px" />
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <Setter Property="Padding" Value="12,8,10,4" />
            </Style>

            <!-- ウィンドウ最大化時に枠幅を変更するためのスタイル-->
            <Style x:Key="MaximumStyle" TargetType="Grid">
                <Setter Property="Background" Value="{StaticResource WindowColor}"/>
                <Setter Property="Margin" Value="6"/>
            </Style>
            <Style x:Key="NormalStyle" TargetType="Grid">
                <Setter Property="Background" Value="{StaticResource WindowColor}"/>
                <Setter Property="Margin" Value="0"/>
            </Style>
            
        </ResourceDictionary>
    </ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

ウィンドウ定義は以下通りです。
標準ボタンの代わりになるコントロールをごりごり書いています。
<Window x:Name="SampleWindow" x:Class="Sample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SampleApplication" Height="240" Width="360" Background="#FF8F99A0" SnapsToDevicePixels="True" MinWidth="256" MinHeight="128" StateChanged="SampleWindow_StateChanged">

    <WindowChrome.WindowChrome>
        <WindowChrome UseAeroCaptionButtons="False" CaptionHeight="24" ResizeBorderThickness="8" />
    </WindowChrome.WindowChrome>

    <Window.Resources>
        <ResourceDictionary Source="SampleStyle.xaml" />
    </Window.Resources>

    <Border BorderBrush="Black" BorderThickness="1">
        <Grid x:Name="BaseGrid" Style="{StaticResource NormalStyle}">

            <!-- タイトルバー領域 -->
            <Image x:Name="WindowIcon" Margin="4,4,0,0" Source="icon.png" Stretch="Fill" Width="32" Height="32" HorizontalAlignment="Left" VerticalAlignment="Top"/>
            <TextBlock x:Name="WindowTitle" HorizontalAlignment="Left" Margin="44,12,0,0" Text="Sample Application" VerticalAlignment="Top"/>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top">
                <Button x:Name="MinimizeButton" Content="0" Style="{StaticResource SystemButton}" FontWeight="Bold" Click="MinimizeButton_Click" />
                <Button x:Name="MaximizeButton" Content="1" Style="{StaticResource SystemButton}" Click="MaximizeButton_Click" />
                <Button x:Name="CloseButton" Content="r" Style="{StaticResource SystemButton}" Click="CloseButton_Click" />
            </StackPanel>

            <!-- クライアント領域 -->
            <Grid x:Name="ClientGrid" Margin="0,40,0,0" Background="{StaticResource ClientColor}">
                <Menu Height="24" VerticalAlignment="Top" Background="{StaticResource WindowColor}">
                    <MenuItem Header="ファイル(_C)"/>
                    <MenuItem Header="編集(_E)"/>
                    <MenuItem Header="ヘルプ(_H)"/>
                </Menu>
            </Grid>

        </Grid>
    </Border>
</Window>

ウィンドウのコードは以下の通りです。
コマンドバインドがまだよくわかっていないので、イベントで実装しています。
標準ボタンの置き換えですが、最大化ボタンのみウィンドウの状態で挙動を変化させるようにしています。

最大化時にウィンドウ端のボタン等が見きれてしまうため、コンテンツが画面内に収まるようにスタイルを切り替えてMarginを変えることで対応しています。ですが、正しい方法じゃないよねこれ。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 Sample
{
    /// 
    /// MainWindow.xaml の相互作用ロジック
    /// 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        // 閉じるボタン
        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            SystemCommands.CloseWindow(this);
        }

        // 最小化ボタン
        private void MinimizeButton_Click(object sender, RoutedEventArgs e)
        {
            SystemCommands.MinimizeWindow(this);
        }

        // 最大化ボタン
        //ウィンドウ状態によってはウィンドウサイズ復帰動作になる
        private void MaximizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
                SystemCommands.RestoreWindow(this);
            else
                SystemCommands.MaximizeWindow(this);
        }

        // ウィンドウ状態が変化したら最大化ボタン記号を変更する
        // 最大化状態になったときに画面外まで表示されるのを防ぐためにスタイルを
        // 変更して画面内にコンテンツが収まるようにする
        private void SampleWindow_StateChanged(object sender, EventArgs e)
        {
            if (this.WindowState == WindowState.Maximized)
            {
                this.BaseGrid.Style = (Style)(this.Resources["MaximumStyle"]);
                this.MaximizeButton.Content = "2";
            }
            else
            {
                this.BaseGrid.Style = (Style)(this.Resources["NormalStyle"]);
                this.MaximizeButton.Content = "1";
            }
        }
    }
}
こんなかんじで、それっぽいウィンドウになります。

0 件のコメント:

コメントを投稿