主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

WPF: ZuneライクなGUIのアプリケーションを作る

                
To Make a Zune-like Window

 Windows7を使い始めたころ、ウィンドウのフレームに透過処理ができてそれはまあきれいでかっこいいものだと思った。だけど少し時間が経つと、そのためにCPUリソースを消費するのもなんだかなと考えて切るようになった。

 最近、ZuneやSteamのクライアントを使ってみて、これはかっこいいと思った。これらにはウィンドウのフレームがないのだ。
120925.jpg

 WPFにはこのウィンドウを再現できるテーマがデフォルトでは入っていないようで、DLLを落としてなおかつXAMLを少しいじる必要があった。そのメモ。


 さきほどのウィンドウを作るのに一番簡単な手立ては、WPFでウィンドウの宣言時にフレームをなしにしてしまうことだ。これならば追加のDLLはいらない。ただ、そうするとこのフレームなしウィンドウはほかのデスクトップ要素に影を落とさなくなってしまう。だからその方法は却下。

 ウィンドウの外周を透明にして影を描画し、その中にGridを配置してそれをウィンドウとして扱うやり方も見つけた。だがこれは常に描画にCPUを消費せねばならなくなるので、この方法も却下。

 ではどうするかというと、Microsoft.Windows.Shell.dllを落として使えばいい。このツールは個人のものではなくMicrosoft製のようだ。DLLの配布場所と使い方の参考になるものを合わせてリンクしておく。
http://archive.msdn.microsoft.com/WPFShell
http://stackoverflow.com/questions/7369115/maximum-custom-window-loses-drop-shadow-effect

 リンク先の真似をすれば、フレームなしの影付きウィンドウが作れる。あともう一歩、ウィンドウをドラッグするためのタイトルバーと、クローズや最大化に使うボタン群をつけたい。以下を参考にした。
http://msdn.microsoft.com/ja-jp/library/microsoft.windows.shell(v=vs.100)
http://www.kanazawa-net.ne.jp/~pmansato/wpf/wpf_ctrl_windowchrome.htm

 これまでのステップを踏むと、以下のようなウィンドウが作れる。IronPythonから使う場合は、スクリプトにDLLへの参照を記すること。
clr.AddReference('Microsoft.Windows.Shell')

ボタンに使う×記号などは画像を用意しなくても、Marlettというフォントを使えば表現できる。指でタップすることを考え、既存のアプリと比較してボタンの間隔を開けてある。参考XAMLを記事の末尾に付けた。
120923.png


<?xml version="1.0" encoding="utf-8"?>
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title=""
FontFamily="Meiryo UI"
Width="800"
MinWidth="350"
Height="700"
Name="window"
WindowStartupLocation="CenterScreen"
WindowStyle="SingleBorderWindow"
ResizeMode="CanResizeWithGrip" >
<Window.CommandBindings>
<CommandBinding Command="{x:Static shell:SystemCommands.CloseWindowCommand}"
Executed="close_window"/>
<CommandBinding Command="{x:Static shell:SystemCommands.MaximizeWindowCommand}"
Executed="state_change"/>
<CommandBinding Command="{x:Static shell:SystemCommands.MinimizeWindowCommand}"
Executed="minimize_window"/>
</Window.CommandBindings>
<Window.Style>
<Style TargetType="Window">
<Setter Property="shell:WindowChrome.WindowChrome">
<Setter.Value>
<shell:WindowChrome GlassFrameThickness="1" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<Grid>
<Border BorderThickness="0.8" BorderBrush="Aqua">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,50" MappingMode="Absolute">
<GradientStop Offset="0" Color="DimGray"/>
<GradientStop Offset="1" Color="Black"/>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter Margin="0" Content="{TemplateBinding Content}"/>
</Border>

<!-- Title プロパティを表示する -->
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Top" Margin="34,8,0,0" Foreground="White"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title}" />

<!-- 最小化、最大化、閉じるボタン -->
<StackPanel Orientation="Horizontal" Margin="0,6,6,0" HorizontalAlignment="Right" VerticalAlignment="Top">
<Button shell:WindowChrome.IsHitTestVisibleInChrome="True"
Height="24" Margin="30,0,0,0" Width="28"
Background="Black"
BorderThickness="0"
Command="{x:Static shell:SystemCommands.MinimizeWindowCommand}"
CommandParameter="{Binding ElementName=window}">
<TextBlock Foreground="White">_</TextBlock>
</Button>
<Button shell:WindowChrome.IsHitTestVisibleInChrome="True"
Height="24" Margin="30,0,0,0" Width="28"
Background="Black"
Command="{x:Static shell:SystemCommands.MaximizeWindowCommand}"
CommandParameter="{Binding ElementName=window}">
<TextBlock Foreground="White" FontFamily="Marlett">1</TextBlock>
</Button>
<Button shell:WindowChrome.IsHitTestVisibleInChrome="True"
Height="24" Margin="30,0,20,0" Width="28"
Background="Black"
Command="{x:Static shell:SystemCommands.CloseWindowCommand}"
CommandParameter="{Binding ElementName=window}">
<TextBlock Foreground="White" FontFamily="Marlett">r</TextBlock>
</Button>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Style>
<StackPanel></StackPanel>
</Window>




質問をいただいたので追記
> 最大化ボタンを押すと、そのあとずっとボタンが点滅しっぱなしなのです。
ButtonコントロールにデフォルトでStyleが適用されていて、
おそらくフォーカス絡みのイベントでアニメーションが働いている。

一つの解としては自分でStyleを定義して、Buttonにそれを適用。
<Style
x:Key="ButtonStyle1"
TargetType="{x:Type Button}" >
<Setter
Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter
Property="VerticalContentAlignment"
Value="Center" />
<Setter
Property="Foreground"
Value="LightGray" />
<Setter
Property="TextBlock.TextAlignment"
Value="Center" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type Button}">
<Border
Background="AliceBlue"
BorderBrush="Gray"
BorderThickness="1"
Margin="0,0,0,0">
<Border.Triggers>
<EventTrigger
RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard
TargetProperty="Background.Color">
<ColorAnimation
To="Azure"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger
RoutedEvent="Border.MouseLeave">
<BeginStoryboard>
<Storyboard
TargetProperty="Background.Color">
<ColorAnimation
To="AliceBlue"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Border.Triggers>
<ContentPresenter
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

上記をWindow.Resourcesの入れ子にしておいて、下記のようにButtonを定義する。
<Button
Style="{StaticResource ButtonStyle1}"
Height="24"
Width="28" >
<TextBlock
Foreground="Black"
FontFamily="Marlett" >r</TextBlock>
</Button>
            

コメントの投稿

非公開コメント

質問

はじめまして。

ここの記事を見て、ZuneライクなGUIのアプリケーションを作りたいと思い
やってみました。

かっこいいですが、ひとつ問題が・・・・・・・

最大化ボタンを押すと、そのあとずっとボタンが点滅しっぱなしなのです。
これを回避できないでしょうか?

よろしくお願いします。

Re: 質問

> 最大化ボタンを押すと、そのあとずっとボタンが点滅しっぱなしなのです。
> これを回避できないでしょうか?
コメントだとタグやインデントが無効になるようなので、本文に追記という形で答えておきました。
プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。