• 検索結果がありません。

グラフィックス 目次

N/A
N/A
Protected

Academic year: 2021

シェア "グラフィックス 目次"

Copied!
43
0
0

読み込み中.... (全文を見る)

全文

(1)

■ 第7 回 WPF UI 要素の基礎とレイアウト用のパネルを学ぼう ■ 前回までで、XAML/WPF の基礎的な仕組みについての説明を終え、今回からは個々の UI(ユーザー・ インターフェイス)要素の説明に入っていく。まず今回は、WPF の UI 要素を表すクラスの継承階層と、 レイアウト用のパネルについて説明する。 ■ UI 要素の継承階層 WPF の UI 要素について MSDN ライブラリで調べて見ると、クラスの継承階層の深さに驚くかもしれ ない。例えば、Button クラス(System.Windows.Controls 名前空間)のページを見てみると、Figure 1 に示すような継承階層が書かれている。

Figure 1: Button クラスの継承階層

WPF の UI 要素も.NET Framework のクラスとして作られているので、Object クラス(=すべてのク ラスに共通の基底クラス)を継承しているのは当然として、その下に多くのクラスが並んでいる。コン トロールの共通基底クラスである Control クラス(System.Windows.Controls 名前空間)より上に 5 つのクラスが並んでいるが、これらの5 つについて簡単に説明しておこう。 (1)DisptacherObject クラス DispatcherObject クラス(System.Windows.Threading 名前空間)は、単一のスレッドのみが直接操 作可能なオブジェクトを表すクラスで、ほかのスレッドからは「ディスパッチャ(Dispatcher: 配送 係り)」と呼ばれるオブジェクトを介してアクセスしなければならない。 WPF では(WPF に限らず、グラフィックを扱うほとんどのフレームワークでは)、パフォーマンス上

W

W

P

P

F

F

(2)

の理由から、UI 要素に対する操作を単一のスレッド上で行わなければならない(このようなスレッド を「UI スレッド」と呼ぶ)。 ところが一方で、UI スレッド上で時間のかかる(描画以外の)処理をしてしまうと、アプリケーショ ンそのものをフリーズさせてしまうことになる。このような処理はUI スレッドとは別のスレッドで行 わなければならない。 実際に時間のかかる処理を別スレッドで行い、その結果に応じてUI 要素の状態を変更したい場合には、 別スレッドからUI スレッドに処理を戻す必要があり、この作業を担うのがディスパッチャである(つ まり、「作成元のスレッドでこの処理を実行してほしい」というメッセージを配送する)。Windows フ ォ ー ム で は 、 コ ン ト ロ ー ル 自 身 が こ の 役 割 を 担 っ て い た が 、WPF で は Dispatcher ク ラ ス (System.Windows.Threading 名 前 空 間 ) に 役 割 を 分 離 し て い る ( DispatcherObject ク ラ ス の Dispatcher プロパティを通して利用)。 例えば、ボタンが押されたときに何か時間のかかる処理を開始し、処理中はボタンを押せなくしたいと いうような場合には、List 1 に示すようなコードを書く必要がある。 Visual Basic

Private Sub StartButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles StartButton.Click

Dim dispatcher = Me.Dispatcher

Dim asyncWork As Action = Sub() HeavyWork() dispatcher.Invoke( New Action( Sub() ' 処理が完了したらボタンを利用可能に戻す Me.StartButton.IsEnabled = True End Sub)) End Sub ' いったんボタンを利用不可にする Me.StartButton.IsEnabled = False asyncWork.BeginInvoke(Nothing, Nothing) End Sub

Private Shared Sub HeavyWork()

' 時間のかかる処理を Sleep を使って疑似的に作る System.Threading.Thread.Sleep(3000)

(3)

Visual C#

private void StartButton_Click(object sender, RoutedEventArgs e) {

var dispatcher = this.Dispatcher; Action asyncWork = () => { HeavyWork(); dispatcher.Invoke(new Action(() => { // 処理が完了したらボタンを利用可能に戻す this.StartButton.IsEnabled = true; })); }; // いったんボタンを利用不可にする this.StartButton.IsEnabled = false; asyncWork.BeginInvoke(null, null); }

private static void HeavyWork() {

// 時間のかかる処理を Sleep を使って疑似的に作る System.Threading.Thread.Sleep(3000);

}

List 1: ディスパッチャの利用例(上:C#、下:VB)

※ XAML コード中に StartButton という名前の<Button>要素があり、Click イベントに Button_Click メソッドが結び付けられているものとする。 (2)DependencyObject クラス 第3 回で説明したように、WPF では「依存関係プロパティ」という独自の「値の保持機構」を持って いる。DependencyObject クラス(System.Windows 名前空間)は、この依存関係プロパティを利用す るための共通基底クラスとなる。 (3)Visual クラス

(4)

Visual クラス(System.Windows.Media 名前空間)は、画面への描画にかかわる要素の共通基底クラ スとなる。 WPF の理念の 1 つに、データ駆動による UI の作成というものがある。すなわち、データとして UI 記 述を行い、フレームワークの内部でデータを実際の描画命令に置き換えてUI を表示する。 例えば、画面上に円を描画したい場合、Windows フォームでは List 2 に示すように、(基本的に)ペイ ント・イベントを拾って描画のための手続きを書いていた。 Visual Basic

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs) Dim g = e.Graphics

Dim pen = New Pen(Color.Blue) g.DrawEllipse(pen, 0, 0, 100, 100) End Sub

Visual C#

protected override void OnPaint(PaintEventArgs e) {

var g = e.Graphics;

var pen = new Pen(Color.Blue); g.DrawEllipse(pen, 0, 0, 100, 100); }

List 2: Windows フォームでの円の描画

これに対してWPF では、List 3 の C#/VB コード、もしくは、List 4 の XAML コードに示すように、 データの宣言によって描画を(単に表示だけでなく、ヒット・テストなども)制御する。

XAML

<Ellipse Width="100" Height="100"

Stroke="Blue" StrokeThickness="1" />

Visual Basic

Me.Content = New Ellipse With { .Width = 100,

.Height = 100,

.Stroke = New SolidColorBrush(Colors.Blue), .StrokeThickness = 1

}

Visual C#

this.Content = new Ellipse {

Width = 100, Height = 100,

Stroke = new SolidColorBrush(Colors.Blue), StrokeThickness = 1,

};

(5)

このような描画に関連するデータに応じて、以下のような処理を行うのがVisual クラスの役割である。 ・画面への実際の表示 ・(拡大・縮小、回転などの)変形 ・クリッピング ・ヒット・テスト(=要素がクリックされたかどうかの判定) (4)UIElement クラス UIElement クラス(System.Windows 名前空間)は UI 要素として必要な最低限の機能を備える共通基 底クラスで、以下のような処理を行う。 ・レイアウト(=要素のサイズや配置の決定)用の抽象メンバ ・ユーザー入力への応答 ・ルーティング・イベントの発生 ・最低限の(一般的な)アニメーション (5)FrameworkElement クラス

FrameworkElement クラス(System.Windows 名前空間)は、UIElement クラスに以下のような WPF 固有の機能を追加したものである。 ・レイアウトの具体的な実装 ・スタイル ・プロパティ値の包含継承 ・WPF 固有のアニメーション(ストーリーボードなど) WPF の UI 要素となるクラスのほとんどは、この FrameworkElement クラスを継承している。 UIElement クラスと FrameworkElement クラスは、将来的な拡張や第三者によるフレームワーク開発 を想定して2 層に分けられている。このため、アセンブリも、汎用的な利用を想定した PresentationCore アセンブリ(UIElement クラスを含む)と、WPF 固有の機能を集めた PresentationFramework アセ ンブリ(FrameworkElement クラスを含む)の 2 層に分かれている。 【コラム】画面描画の共通基底クラスに関する補足: Freezable クラス

(6)

ブラシやアニメーションのタイムラインなど、描画に関連はするが、直接画面に描画されるわけでは ないもの(つまり、Visual クラスには適さないもの)もあり、このような要素の場合は Freezable ク ラス(System.Windows 名前空間)を継承する。 Freezable クラスは、オブジェクトの状態を固定(freeze)して読み取り専用にできる(書き込み可 能なものを途中から読み取り専用に切り替えられるので、不変(immutable)ではなく固定可能 (freezable)と呼ぶ)。 DispatcherObject クラスの項で説明したとおり、パフォーマンス上の理由から、グラフィックに関連 する要素は単一のスレッドからのみアクセス可能になっている場合が多いが、読み取り専用であれば ほかのスレッドからアクセスされても問題は生じない。Freezable クラスの場合、オブジェクトが固 定された状態(frozen)のときだけ、ほかのスレッドからのアクセスを許可している。 FrameworkElement クラスの下にはさまざまな派生クラスが存在する。今回は、まず、レイアウト用 のパネルについて説明していこう。 ■ パネル(レイアウト用の UI 要素) WPF には柔軟なレイアウトを簡単に実現するための仕組みが備わっている。ここでは、レイアウトの 背景、基礎的な概念、および、標準で提供されているレイアウト用のパネルについて説明していく。 背景 かつて技術が未成熟だったころ、GUI アプリケーションは固定レイアウト(要素のサイズや配置をすべ てハード・コーディング)になることが多かったが、技術の進歩とともに、柔軟なレイアウトが可能と なった。レイアウトを柔軟にすることには以下のような利点がある。 ○多様な表示方法への対応 以下に挙げるような理由から、GUI アプリケーションは環境ごとに表示方法が異なってくる。 ・ハードウェア上の制約: PC の場合、ディスプレイのサイズは機器ごとにかなりの差がある。 ・利用者の嗜好: ある人は全画面表示を好み、ある人は小さくしたウィンドウを複数並べることを好 むなど、利用者ごとに好むウィンドウ・サイズが異なる。 ・アクセシビリティ: 弱視や老眼の人の利用が想定される場合、フォント・サイズは容易にカスタマ イズ可能にする必要がある。 固定レイアウトでは、このような多様な表示方法への対応は難しい。 ○多言語対応 文章の長さは使用言語ごとに異なり、特に例えば、漢字文化圏とアルファベット文化圏では長さが倍以 上変わる場合もある。 多言語対応が必要な場合に固定レイアウトを行っていると、言語によって文字が途中で切れるか、逆に 余白が残りすぎるなどといった問題が生じる。柔軟なレイアウト手法によってサイズや配置を自動調整 できれば、他言語対応に伴う GUI の再調整作業は必要なくなり、他言語対応の手間をほぼ翻訳の手間

(7)

だけにできる。

WPF のレイアウトの基礎概念

柔軟なレイアウトを実現するため、WPF の UI 要素は自分自身だけでなく、レイアウト用のパネル(後 述するCanvas や Grid など)などを親要素とし、Figure 2 に示すように、親子間で協調しながらサイ ズや配置を決定していく。 親子間の協調のため、UIElement クラスには以下のようなメソッドが用意されている。 ・DesiredSize プロパティ: 要素が希望するサイズ。 ・Measure メソッド: 親要素から利用可能な領域サイズを渡し、DesiredSize プロパティの値を更新 する。 ・Arrange メソッド: 実際に要素のサイズや配置を決定する。 希望サイズを測るだけのMeasure メソッドと実際にサイズや配置を決定する Arrange メソッドに分か れているのは、正式にレイアウトを決定するまでの間に、ほかの要素との兼ね合いで何度も測り直しが 発生するためである。 ○希望サイズの決定 Measure での希望サイズや配置の決定に当たって、FrameworkElement クラスは以下のようなプロパ ティを持っている。 ・Width, Height: 幅、高さを具体的に指定する。ただし、親要素によって希望サイズが拒否される可 能性もあるため、必ずしもこの値が最終的なサイズにはならない。

・MinWidth, MaxWidth, MinHeight, MaxHeight: 幅、高さの最小値、最大値を指定する。 ・Margin: 要素の外側の余白幅を指定する。

・HorizontalAlignment, VerticalAlignment: 配置される空間よりも要素のサイズの方が小さい場合に、 要素を上下左右のどちらに寄せるかを指定する。

(8)

Width プロパティと Height プロパティを用いることで、具体的な幅、高さを直接指定することも可能 ではあるが、思ったとおりの見た目を得やすい半面、前述のような多様な表示方法への適応力が弱まる という問題もある。具体的な値の指定は可能な限り避けた方がいいだろう。

また、このWidth プロパティや Height プロパティはあくまで希望サイズを指定するためのものであっ て、レイアウト決定後の実際の値ではない。これらのプロパティを指定せず、親要素や子要素に応じて サイズを自動決定した場合、その値はデフォルト値(NaN: Not a Number、無効な数値)のままにな っている。レイアウト決定後の値を取得したい場合には、ActualWidth プロパティと ActualHeight プ ロパティを利用する。 標準提供されるパネル WPF で標準提供されているパネルを紹介していこう。ここで紹介するクラスはいずれも Panel クラス (System.Windows.Controls 名前空間)の派生クラスとなっている。 ○StackPanel StackPanel クラス(System.Windows.Controls 名前空間)では、子要素を縦または横一列に整列する。

List 5 に示すように特に何も指定しなければ縦に、List 6 に示すように Orientation 属性で「Horizontal」 を指定すると横に整列する。List 5、List 6 の実行結果をそれぞれ Movie 1、Movie 2 に示す。

<Window x:Class="atmarkit07.Panels.StackPanelSample"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="StackPanel(縦)" Height="300" Width="300">

<StackPanel>

<Button Content="幅指定なし" />

<Button Content="幅 100 右寄せ" HorizontalAlignment="Right" /> <Button Content="幅 100 中央" HorizontalAlignment="Center" /> <Button Content="幅 100 左寄せ" HorizontalAlignment="Left" /> <Button Content="幅 200~250" MinWidth="200" MaxWidth="250" /> <Button Content="余白 30" Margin="30" />

</StackPanel> </Window> List 5: StackPanel(縦)の例(XAML) https://www.youtube.com/watch?v=9zE-tUkLhd0&feature=player_embedded Movie 1: StackPanel(縦)の実行例 <Window x:Class="atmarkit07.Panels.StackPanelHorizontalSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

(9)

Title="StackPanel(横)" Height="300" Width="300"> <Window.Resources> <Style TargetType="Button"> <Setter Property="LayoutTransform"> <Setter.Value> <RotateTransform Angle="-90" /> </Setter.Value> </Setter> </Style> </Window.Resources> <StackPanel Orientation="Horizontal"> <Button Content="高さ指定なし"/>

<Button Content="高さ 100 上寄せ" VerticalAlignment="Top" /> <Button Content="高さ 100 中央" VerticalAlignment="Center" /> <Button Content="高さ 100 下寄せ" VerticalAlignment="Bottom" /> <Button Content="高さ 200~250" MinWidth="200" MaxWidth="250"/> <Button Content="余白 30" Margin="30" />

</StackPanel> </Window> https://www.youtube.com/watch?v=ATfDlHgjIY4&feature=player_embedded Movie 2: StackPanel(横)の実行例 ○WrapPanel WrapPanel クラス(System.Windows.Controls 名前空間)では、子要素を左から右に順番に並べ、幅 を超えた分は右端で折り返すようにレイアウトする。HTML でのインライン要素のレイアウトを想像す るといいだろう。

List 8 に WrapPanel の利用例となる XAML コードを、Movie 3 にその実行結果を示す。

<Window x:Class="atmarkit07.Panels.WrapPanelSample"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="WrapPanelSample" Height="300" Width="300">

<WrapPanel>

<Button Content="1" Height="80" /> <Button Content="上寄せ"

Width="80" VerticalAlignment="Top" /> <Button Content="中央"

(10)

Width="80" VerticalAlignment="Center" /> <Button Content="下寄せ" Width="80" VerticalAlignment="Bottom" /> <Button Content="上寄せ" Width="80" VerticalAlignment="Top" /> <Button Content="中央" Width="80" VerticalAlignment="Center" /> <Button Content="下寄せ" Width="80" VerticalAlignment="Bottom" /> </WrapPanel> </Window>

List 7: WrapPanel の例(XAML)

https://www.youtube.com/watch?v=-tDIc-paDiE&feature=player_embedded Movie 3: WrapPanel の実行例 ○DockPanel DockPanel クラス(System.Windows.Controls 名前空間)では、パネルの上下左右に子要素を貼り付 ける(ドッキング)ようにレイアウトする。ドッキングする位置はDockPanel.Dock 属性(実体は添付 プロパティ)によって行う。

List 8 に DockPanel の利用例となる XAML コードを、Movie 4 にその実行結果を示す。

<Window x:Class="atmarkit07.Panels.DockPanelSample"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="DockPanel" Height="300" Width="300">

<Window.Resources>

<Style TargetType="Button">

<Setter Property="Padding" Value="15" /> </Style>

</Window.Resources>

<DockPanel>

<Button Content="1" DockPanel.Dock="Left" Background="#ffcccc" />

<Button Content="2" DockPanel.Dock="Top" Background="#ccffcc" />

<Button Content="3" DockPanel.Dock="Right" Background="#ccccff" />

<Button Content="4" DockPanel.Dock="Bottom" Background="#ccffff" />

(11)

<Button Content="5" DockPanel.Dock="Left" Background="#ffffcc" />

<Button Content="6" DockPanel.Dock="Right" Background="#ffccff" />

<Button Content="7"

Background="#ffffff" />

</DockPanel>

</Window>

List 8: DockPanel の例(XAML)

https://www.youtube.com/watch?v=S2NVaRDsJoo&feature=player_embedded Movie 4: DockPanel の実行例

○Canvas

あ ま り 場 面 は 多 く な い が 、 ど う し て も 固 定 レ イ ア ウ ト が 必 要 な と き に は Canvas ク ラ ス (System.Windows.Controls 名前空間)を利用する。配置の指定は Canvas.Left 属性や Canvas.Top 属性(いずれも実体は添付プロパティ)を用いて行う。

List 9 に Canvas の利用例となる XAML コードを、Figure 3 にその実行結果を示す。

<Window x:Class="atmarkit07.Panels.CanvasSample"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Canvas" Height="300" Width="300">

<Canvas>

<Button Canvas.Left="23" Canvas.Top="26" Content="A" Height="53" Width="53" Background="#ffcccc" /> <Button Canvas.Left="55" Canvas.Top="103" Content="B" Height="53" Width="53" Background="#ccffcc" /> <Button Canvas.Left="119" Canvas.Top="12" Content="C" Height="53" Width="53" Background="#ccccff" /> <Button Canvas.Left="158" Canvas.Top="85" Content="D" Height="53" Width="53" Background="#ccffff" />

</Canvas>

</Window>

(12)

Figure 3: Canvas の実行例

○Grid

Grid クラス(System.Windows.Controls 名前空間)は、表形式(列位置と行位置の指定)でレイアウ トを行う。

Visual Studio のウィンドウのテンプレートで使われているため、目にする機会は多いだろう。ただし、 Visual Studio の視覚デザイン・ツールを利用すると、表形式といっても、余白(Margin 属性)やサイ ズ(Width 属性と Height 属性)を使った固定的なレイアウトになりがちである。Windows フォーム時 代と同じ感覚でレイアウトができて手軽ではあるものの、多様な表示方法に対応するためには注意が必 要である。 表を何行・何列にするかや、各列の幅、各行の高さを決めるために、<Grid>要素の RowDefinitions プ ロパティ、および、ColumnDefinitions プロパティを設定する。列の幅、および、行の高さには、以下 のように3 種類の指定方法がある。 ・固定値指定: 「Width="100"」というように、数値のみを与えると、固定幅/高さになる。 ・比率指定: 「Width="2*"」というように、数値の後ろにアスタリスクを付けると、比率指定となる。 <Grid>要素自身のサイズ変更に応じて、比率を保ったまま行/列のサイズも変化する。 ・自動: 「Width="auto"」というように、「auto」を指定すると、子要素のサイズに応じて行/列のサ イズが自動調整される。 また、子要素を何行目・何列目に配置するかを指定するため、Grid.Row 属性、および、Grid.Column 属性(いずれも実体は添付プロパティ)を設定する。複数行・複数列にまたがる子要素を作るためには、 Grid.RowSpan 属性および Grid.ColumnSpan 属性を指定する。

List 10 に Grid の利用例となる XAML コードを、Movie 5 にその実行結果を示す。

<Window x:Class="atmarkit07.Panels.GridSample"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

(13)

Title="Grid" FontSize="16" Height="320" Width="480"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50" /> <RowDefinition Height="50" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="150" /> <ColumnDefinition Width="150" /> <ColumnDefinition Width="150" /> </Grid.ColumnDefinitions> <Button Content="固定幅" Background="#ffcccc" />

<Button Content="A" Background="#ccffcc" Grid.Column="1" />

<Button Content="B" Background="#ccccff" Grid.Column="2" />

<Button Content="190" Background="#ccffff" Grid.Row="1" />

<Button Content="190" Background="#ffccff" Grid.Row="1" Grid.Column="1" /> <Button Content="190" Background="#ffffcc" Grid.Row="1" Grid.Column="2" /> </Grid> <Grid Grid.Row="1"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="2*" /> <ColumnDefinition Width="3*" /> <ColumnDefinition Width="4*" /> </Grid.ColumnDefinitions>

(14)

<Button Content="比率" Background="#ffcccc" /> <Button Content="A" Background="#ccffcc" Grid.Column="1" />

<Button Content="B" Background="#ccccff" Grid.Column="2" />

<Button Content="2*" Background="#ccffff" Grid.Row="1" />

<Button Content="3*" Background="#ffccff" Grid.Row="1" Grid.Column="1" /> <Button Content="4*" Background="#ffffcc" Grid.Row="1" Grid.Column="2" /> </Grid> <Grid Grid.Row="2"> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="auto" /> </Grid.ColumnDefinitions> <Button Content="自動" Background="#ffcccc" /> <Button Content="━━━長いテキスト━━━" Background="#ccffcc" Grid.Column="1" /> <Button Content="短い" Background="#ccccff" Grid.Column="2" /> <Button Content="auto" Background="#ccffff" Grid.Row="1" /> <Button Content="短い" Background="#ffccff" Grid.Row="1" Grid.Column="1" /> <Button Content="━━━長いテキスト━━━" Background="#ffffcc" Grid.Row="1" Grid.Column="2" /> </Grid> </Grid> </Window>

List 10: Grid の例(XAML)

(15)

Movie 5: Grid の実行例 特に、「auto」はフォント・サイズの変更と相性がよい。また、多言語対応によって文字幅が変化した 場合にも自動的に対応できる。 Movie 6 に例を示そう。この例では、コントロール・キーを押しながらマウス・ホイールを回すとフォ ント・サイズが変化するコードを記述している。<Grid>要素の行・列のサイズは「auto」を指定してあ り、フォント・サイズの変化に、行・列のサイズが追従している。 https://www.youtube.com/watch?v=uW45VfjxCmc&feature=player_embedded Movie 6: フォント・サイズの変更の例 場合によっては、<Grid>要素の行・列のサイズを動的に変更したい場合もあるだろう。そういう場合、 List 11 に示すように、<Grid>要素の子に<GridSplitter>要素を配置する。実行結果は Movie 7 に示す ようになる。

<Window x:Class="atmarkit07.Panels.SplitterSample"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="スプリッター" Height="300" Width="300" FontSize="20">

<Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions>

<Button Content="A" Background="#ffcccc" />

<Button Content="B" Background="#ccffcc" Grid.Column="2"/> <Button Content="C" Background="#ccccff" Grid.Row="2" /> <Button Content="D" Background="#ccffff" Grid.Row="2" Grid.Column="2"/> <GridSplitter Grid.Row="1" Grid.ColumnSpan="3" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center" /> <GridSplitter Grid.Column="1" Grid.RowSpan="3" Width="5" HorizontalAlignment="Center" VerticalAlignment="Stretch" />

</Grid>

(16)

List 11: GridSplitter の例(XAML) https://www.youtube.com/watch?v=E9EFmZAJG_0&feature=player_embedded Movie 7: GridSplitter の実行例 ただし、<GridSplitter>要素を利用する場合、以下のような注意点がある。 ・<GridSplitter>要素自体、<Grid>要素のセルを 1 つ占有する。そのため、一般的には、<GridSplitter> 要素を配置するための行・列を「auto」指定で作成しておく ・<GridSplitter>要素は、デフォルトの状態では幅も高さも「0」で不可視となる。HorizontalAlignment 属性などを指定して、見えるサイズに調整する必要がある ・「特定の1 行だけ列幅を変えたい」というようなことは、1 つの<Grid>要素内では行えない。もしそ の必要があるなら、<Grid>要素を入れ子にして、内側の<Grid>要素だけに<GridSplitter>要素を追 加するなどの工夫が必要になる ○そのほか そのほかにも、いくつかPanel クラスの派生クラスがある。ここでは 2 つのクラスを簡単に紹介してお こう(いずれもSystem.Windows.Controls 名前空間)。 ・UniformGrid クラス: すべての行・列が同じサイズの単純な表形式でレイアウトを行う。柔軟性は ないものの、描画の性能はよい。 ・VirtualizingPanel クラス: 子要素を仮想化する(スクロールされるまで隠れていて見えない子要素 を、実際に表示されるタイミングまで、サイズ計測も配置も行わない)ためのパネル。単体で利用す るよりは、次回以降で説明するListBox クラスなどの内部で利用する。 【コラム】パネルに関する補足 ●Z 順序 レイアウトの仕方によっては、UI 要素が重なってしまう場合がある。このとき、特に指定のない場 合、後方で(XAML コード中の下の方で)定義された UI 要素が上に表示される。この順序(慣例的 に「Z 順序(Z-order)」と呼ばれる。横方向を X、縦方向を Y で表すことが多いため、前後関係を Z で表現する)を明示的に指定するには、UI 要素に Panel.ZIndex 添付プロパティを設定する。この添 付プロパティの値が大きいほど手前に表示されることになる。 ●レイアウト丸め WPF では、UI 要素の位置を浮動小数点数で正確に位置を計算していて、自動レイアウトの結果、UI 要素や文字の描画位置が非整数ドットになる場合がある。この際、デフォルトでは、補間処理によっ てUI 要素が非整数ドット位置にあるかのように描画を行う。 このような動作が好ましい場合ももちろんあるが、補間のせいで境界線や文字がにじんで見えるとい う問題もある。

そこで、.NET Framework 4 では、FrameworkElement クラスに UseLayoutRounding プロパティ が追加され、このプロパティを「true」に設定すれば、描画位置が整数ドットになるように位置の丸 め処理を行ってくれるようになった。

(17)

次回は主にコントロールについて説明する。 ■ 第8 回 WPF の「コントロール」を学ぼう ■ レイアウト用のパネルに続き、今回は、「ユーザー/アプリケーション間の対話を担う要素」、いわゆる コントロールを中心として、WPF の UI 要素について説明していく。 ■ コントロール コントロールは、ユーザーとの対話を担う要素で、GUI アプリケーション開発の中心的存在といえる。 コントロールは、マウスやキーボードなどのユーザー操作を受け取ったり、処理の途中経過や結果を適 宜表示したりするために利用する。 コントロールの全体像 まず、コントロールや、関連するUI 要素のクラス階層を見てみよう。主要なものを Figure 1 に示す。 Figure 1: WPF の主要な UI 要素 前回説明したとおり、FrameworkElement クラス(System.Windows 名前空間)は WPF のほとんど のUI 要素の共通基底となる基礎的なクラスで、Panel クラス(System.Windows.Controls 名前空間) は子要素と協調してレイアウトを決定するためのパネルの基底クラスである。 一方、今回初出となる Decorator クラス(System.Windows.Controls 名前空間)は、子要素やその周 辺に何らかの装飾を施すためのクラスで、例えば、UI 要素の回りを枠線で囲ったり、ビュレット(= 個条書き用の中点)を付けたりするために用いる。

(18)

そして、Control クラス(System.Windows.Controls 名前空間)が、今回の主題であるコントロールの 基底クラスとなる。 それではまず、Control クラスをはじめ、さまざまなコントロールの基底クラスとなるいくつかの主要 なクラス(=Figure 1 で、青色の枠線で囲われているもの)について説明していこう。 ■ 主要な基底クラス Control クラス Control クラスはすべてのコントロールの基底となるクラスで、Table 1 に示すようなメンバを持ってい る。 機能 メンバ 外観設定 Background BorderBrush BorderThickness Foreground フォント FontFamily FontSize FontStretch FontStyle FontWeight 内容物のレイアウト決定 HorizontalContentAlignment VerticalContentAlignment Padding フォーカス管理 IsTabStop TabIndex コントロール・テンプレート Template マウス・イベント MouseDoubleClick PreviewMouseDoubleClick Table 1: Control クラスの機能 ※ マウス・イベントの各メンバはルーティング・イベントである。それ以外はすべてプロパティ。 以下、何点か補足説明をしていこう。 ○外観設定

Background プロパティ、Foreground プロパティ、および、BorderBrush プロパティは、それぞれ背 景や前景、枠線の塗りつぶしを行うためのブラシとなっている。純色での塗りつぶしだけでなく、以下 のようなブラシを利用することで、グラデーションや画像を使った塗りつぶしも可能である。

・SolidColorBrush: 純色で塗りつぶす。

(19)

・RadialGradientBrush: 放射状グラデーションで塗りつぶす。 ・ImageBrush: 画像を使って塗りつぶす。

・DrawingBrush: Drawing クラス(=2D 描画)を使って塗りつぶす。

・VisualBrush: Visual クラス(=WPF の UI 要素の共通基底クラス)を使って塗りつぶす。

例 え ば 、DrawingBrush に 対 し て <VideoDrawing> 要 素 を 与 え た り 、 VisualBrush に 対 し て <MediaElement>要素を与えたりすることで、コントロールの背景に動画を表示することも可能である。 SolidColorBrush の場合には、RGB 値や色名からの変換が定義されていて、XAML の属性構文を使っ て以下のような色指定が可能である。 <!-- # 6 ケタの 16 進数で RGB 指定。 --> <TextBox Background="#0000ff" /> <!-- 色名からの変換が働く。 Colors クラスの静的メンバーとして定義されている。 --> <TextBox Background="Blue" /> <!-- SystemColors クラスの静的メンバーを参照することで、 システム色を利用可能。 -->

<TextBox Background="{x:Static SystemColors.ActiveCaptionBrush}" /> XAML の属性構文を使った SolidColorBrush の色指定のコード例(XAML)

どのような色名やシステム色が利用できるかは、MSDN の「Colors クラス(System.Windows.Media 名前空間)」および「SystemColors クラス(System.Windows 名前空間)」のページを参照してほしい。

また、LinearGradientBrush、RadialGradientBrush、および、ImageBrush は、Visual Studio や Expression Blend を使ってブラシの設定が可能である。Movie 1 に、Visual Studio を使ったブラシ設 定の例を示す。

https://www.youtube.com/watch?v=y8qG0dVtrY8&feature=player_embedded Movie 1: Visual Studio を使った背景ブラシの編集

○フォント フォントに関しては、ファミリ、サイズ、スタイル(=標準/太字/斜体/打ち消し線付き/下線付き)、 線の太さ、伸縮と、一通り設定可能になっている。このうち、フォント・ファミリについて補足してお こう。 FontFamily プロパティに単にフォント名を指定した場合、システムにインストールされたフォントが 利用される。当然、指定されたフォントがインストールされていない環境では、そのフォントが適用さ れない(既定のフォントが使用される)。 <!-- システムにインストールされたフォントを使う。 --> <!-- フォントがインストールされていない環境では適用されない。 --> <TextBlock Text="テスト 試作" FontFamily="HGPGyoshotai" /> フォント・ファミリ指定のコード例(XAML)

(20)

システムにフォントがインストールされていない場合を想定して、フォント・ファミリはカンマ区切り で複数指定可能である。 また、どんな環境でも意図したとおりのフォントで表示できるように、アプリケーションにフォントを 埋め込むこともできる。 手順としては、まず、フォントをアセンブリ・リソース(=Visual Studio の[プロパティ]ウィンド ウで[ビルド アクション]を「Resource」にしたもの)としてアプリケーションに埋め込む。そして、 XAML コード中では、「FontFamily="./#font name"」というように、「#」に続けてフォント名を記述 する。 Figure 2 に、フォントの埋め込みの例を示す。 Figure 2: フォントの埋め込みの例 ※ ちなみに、このサンプルで指定している「たぬき油性マジック」は商用利用可能なフリー・フォン ト。 ただし、配布を自由に認めているフォントでも、アプリケーションへ埋め込んでの配布は認めていない 場合があるので、ライセンスに注意が必要である。 ContentControl クラス ContentControl クラス(System.Windows.Controls 名前空間)は、ボタンなどのように、コンテンツ を1 つだけ持つコントロールの基底クラスである。アプリケーション本体となることの多い Window ク ラスもContentControl クラスから派生している。 コンテンツを表す Content プロパティは object 型になっていて、何でも格納することができる。格納 した型によって、以下のように、異なる表示が行われる。

(21)

・UIElement クラスの場合、そのまま UI 要素として表示が行われる(OnRender メソッドで描画を行 う) ・そのほかのクラスの場合、データ・テンプレートが設定されていればテンプレートを使った表示が行 われる(連載第5 回を参照) ・データ・テンプレートも設定されていない場合、ToString メソッドを使って文字列化された結果が表 示される ContentControl クラスの派生クラスの中に複数の UI 要素を並べたい場合、まず<Grid>要素などのパ ネルを置いて、その中にUI 要素を並べる。 コンテンツへのテンプレート適用は、ContentTemplate プロパティで明示的に指定するか、第 5 回で説 明したようにDataType プロパティを使った自動適用で行う。 HeaderedContentControl クラス Figure 3 に示すように、<GroupBox>要素や<Expander>要素など、一部のコントロールはヘッダ情報 とコンテンツを持っている。このようなコントロールの基底となるのがHeaderedContentControl クラ ス(System.Windows.Controls 名前空間)である。 Figure 3: ヘッダとコンテンツを持つコントロールの例

ヘッダ情報を指定するためのHeader プロパティも Content プロパティと同様に object 型となっていて、 データ・テンプレートや ToString メソッドを介した表示が行われる。データ・テンプレートを明示的 に指定したい場合にはHeaderTemplate プロパティを使って指定する。

ItemsControl クラス

ItemsControl クラス(System.Windows.Controls 名前空間)は、<ListBox>要素などのように複数の 項目を持つコントロールの基底クラスである。ItemsControl クラスの内部構造は Figure 4 に示すよう になっていて、以下のように、カスタマイズできる個所が3 つある。

・item: <ItemsControl>要素内に表示したい項目。ItemsSource プロパティを通して与える。 <ContentControl>要素の Content プロパティと同様に、データ・テンプレートが適用可能で、明示

(22)

的にテンプレートを与えたい場合にはItemTemplate プロパティを用いる。 ・container: ItemsSource プロパティで与えた項目は直接表示されるわけではなく、1 段階コンテナ を挟んで表示される。コンテナは、ListBox コントロールなら<ListBoxItem>要素、ComboBox コン トロールなら<ComboBoxItem>要素というように、ItemsControl クラスの派生クラスごとに決まっ ている。コンテナを丸ごと差し替えることはできないが、ItemContainerStyle プロパティを用いる ことでスタイルの変更が可能である。

・item panel: 複数の項目のレイアウトを決定するためのパネル。ItemsPanel プロパティで明示的に 指定することで、レイアウト方法を変えられる。

Figure 4: ItemsControl クラスの内部構造

List 1 に ItemsControl クラスのカスタマイズの例を、Figure 5 にその表示結果を示す。

XAML

<Window x:Class="atmarkit08.ItemsControlSample"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="ItemsControl サンプル" Height="150" Width="150"> <Grid> <ItemsControl ItemsSource="{Binding}"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <CanvasItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemContainerStyle> <Style>

(23)

<Setter Property="Canvas.Left" Value="{Binding X}" /> <Setter Property="Canvas.Top" Value="{Binding Y}" /> </Style>

</ItemsControl.ItemContainerStyle>

<ItemsControl.ItemTemplate> <DataTemplate>

<Button Content="{Binding Text}" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </Window> Visual Basic Me.DataContext = {

New With { .Text = "a", .X = 20, .Y = 80 }, New With { .Text = "b", .X = 80, .Y = 80 }, New With { .Text = "c", .X = 80, .Y = 20 }, New With { .Text = "d", .X = 20, .Y = 20 } }

Visual C#

this.DataContext = new[] {

new { Text = "a", X = 20, Y = 80 }, new { Text = "b", X = 80, Y = 80 }, new { Text = "c", X = 80, Y = 20 }, new { Text = "d", X = 20, Y = 20 }, }; List 1: ItemsControl クラスのカスタマイズの例 Figure 5: List 1 の表示結果 この例では、ItemsPanel プロパティに<Canvas>要素を指定することで、頒布図のようなレイアウトを 行っている。Canvas.Left添付プロパティは<Canvas>要素の直接の子要素に指定する必要があるため、 ItemTemplate プロパティに指定するデータ・テンプレート内ではなく、ItemContainerStyle プロパテ ィに指定するスタイル内で設定しなければならない。

(24)

○コレクション・ビュー ItemsSource プロパティ経由で<ItemsControls>要素に渡されたデータ・ソースは、Figure 6 に示すよ うに、実際には間にコレクション・ビュー(collection view)というものが挟まったうえで表示される。 コレクション・ビューは、データ・ソースを変更せずに、ビュー上でだけデータの整列やグループ化を 行うためのものである。 Figure 6: コレクション・ビュー コレクション・ビューという言葉は、名称に「ビュー」という言葉が入っているのが尐し紛らわしいが、 いわゆる「ビューとモデル」のビュー(見た目に関する部分)のことではなく、データベース用語のビ ュー(=表示用にデータ・ソースを整形したもの)の意味合いで使われている。

ItemsControl クラスの ItemsSource プロパティに、コレクション・ビューを表す ICollectionView イ ンターフェイス(System.ComponentModel 名前空間)のインスタンスを渡すと、それがそのまま表示 されるが、ほかのコレクションを与えた場合には、内部的にコレクション・ビューが作成され、ラッピ ングされる。

ItemsControl クラスには、ItemsSource プロパティのほかに、Items プロパティというものもあるが、 こちらはこのコレクション・ビューに対して直接要素の追加や読み出しを行う場合に利用する。

XAML コード中で明示的にコレクション・ビューを作りたい場合、<CollectionViewSource>要素 (System.Windows.Data 名前空間)を利用する。List 2 にコレクション・ビューの利用例を、Movie 2

(25)

にその実行結果を示す。 XAML <Window x:Class="atmarkit08.CollectionViewSourceSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cm="clr-namespace:System.ComponentModel;assembly=WindowsBase" xmlns:dat="clr-namespace:System.Windows.Data;assembly=PresentationFramework" Title="CollectionView サンプル" Height="500" Width="500">

<Window.Resources>

<CollectionViewSource x:Key="Sorted" Source="{Binding}"> <CollectionViewSource.SortDescriptions>

<cm:SortDescription PropertyName="Category" /> </CollectionViewSource.SortDescriptions>

</CollectionViewSource>

<CollectionViewSource x:Key="Grouped" Source="{Binding}"> <CollectionViewSource.GroupDescriptions> <dat:PropertyGroupDescription PropertyName="Category" /> </CollectionViewSource.GroupDescriptions> </CollectionViewSource> </Window.Resources> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="*" /> <RowDefinition Height="auto" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <TextBlock Text="同じコレクション・ビューを参照" Grid.ColumnSpan="2" HorizontalAlignment="Center" /> <DataGrid

ItemsSource="{Binding}" Grid.Row="1" Grid.Column="0" /> <DataGrid

ItemsSource="{Binding}" Grid.Row="1" Grid.Column="1" />

<TextBlock Text="SortDescription 付き" Grid.Row="2" /> <DataGrid

(26)

ItemsSource="{Binding Source={StaticResource Sorted}}" Grid.Row="3" Grid.Column="0" />

<TextBlock Text="GroupDescription 付き" Grid.Row="2" Grid.Column="1" /> <DataGrid

ItemsSource="{Binding Source={StaticResource Grouped}}" Grid.Row="3" Grid.Column="1"> <DataGrid.GroupStyle> <GroupStyle /> </DataGrid.GroupStyle> </DataGrid> </Grid> </Window> Visual Basic Me.DataContext = {

New With { .Name="Button", .Category="ボタン" }, New With { .Name="CheckBox", .Category="選択" }, New With { .Name="ComboBox", .Category="選択" }, New With { .Name="TextBlock", .Category="文字表示" }, New With { .Name="RadioButton", .Category="選択" }, New With { .Name="RichTextBlock", .Category="文字表示" }, New With { .Name="ScrollBar", .Category="表示" },

New With { .Name="ToolTip", .Category="表示" } }

Visual C#

this.DataContext = new[] {

new { Name="Button", Category="ボタン" }, new { Name="CheckBox", Category="選択" }, new { Name="ComboBox", Category="選択" }, new { Name="TextBlock", Category="文字表示" }, new { Name="RadioButton", Category="選択" }, new { Name="RichTextBlock", Category="文字表示" }, new { Name="ScrollBar", Category="表示" },

new { Name="ToolTip", Category="表示" }, }; List 2: コレクション・ビューの利用例 https://www.youtube.com/watch?v=ZXt0NojyvjI&feature=player_embedded Movie 2: List 2 の実行結果 この例では、2 行 2 列で 4 つの<DataGrid>要素を表示している。上の 2 つは同じデータ・ソースを参 照していて(内部的に生成されるコレクション・ビューも同じものが共有される)、片方での整列の結

(27)

果が他方にも反映される。下の 2 つの<DataGrid>要素には、それぞれ整列およびグループ化されたコ レクション・ビューを与えている。 HeaderedItemsControl クラス Figure 7 に示すように、<MenuItem>要素や<TreeViewItem>要素など、ヘッダ情報と複数の項目を持 っ て い る も の も あ り 、 こ の よ う な コ ン ト ロ ー ル は HeaderedItemsControl ク ラ ス (System.Windows.Controls 名前空間)を基底クラスとしている。 Figure 7: ヘッダと複数の項目を持つコントロールの例 次のページでは、WPF のコントロールを用途ごとに分類する。 ■ コントロールを用途ごとに分類 今度は、WPF が標準提供しているコントロールや関連する UI 要素を、用途ごとに分類して見ていこう。 用途:レイアウト 前回説明したパネル(=複数の子要素と協調的にレイアウトを決定する UI 要素)以外にも、Table 2 に示すように、レイアウトに関係するUI 要素がいくつかある。 分類 UI 要素 説明 レイアウト Window ウィンドウ StackPanel WrapPanel DockPanel 前回参照

(28)

Grid Canvas VirtualizingStackPanel ScrollViewer コンテンツが指定サイズに収まらない場合にスクロ ール可能にする GroupBox グループを表すヘッダと枠線を表示する Expander コンテンツを折りたたんで表示/非表示を切り替え る Viewbox コンテンツを指定サイズになるように拡大/縮小す る TabControl 複数のパネルをタブで切り替える レイアウト部品 Separator メニューなどで使う区切り線 GridSplitter <Grid>要素の行や列の幅/高さを調整するためのス プリッタ ResizeGrip ウィンドウのサイズを変更するためのつまみ ScrollBar スクロールバー Thumb スクロールバーのつまみなど、ユーザーがドラッグできる部分 RepeatButton マウス・ボタンを押し続けている間中クリック・イベ ントが発生するボタン。スクロールバーなどの部品と して使う 装飾 Border UI 要素の回りに枠線を表示する BulletDecorator ビュレット(=個条書き用の中点)を表示する Table 2: レイアウトに関係する UI 要素 ・System.Windows 名前空間に所属するクラス: Window ・System.Windows.Controls 名前空間に所属するクラス: StackPanel、WrapPanel、DockPanel、 Grid、Canvas、VirtualizingStackPanel、ScrollViewer、GroupBox、Expander、Viewbox、TabControl、 Separator、GridSplitter、Border ・System.Windows.Controls.Primitives 名前空間に所属するクラス: ResizeGrip、ScrollBar、Thumb、

(29)

RepeatButton、BulletDecorator

○ウィンドウ

ウィンドウ(=<Window>要素)も ContentControl クラスを継承する一種のレイアウト用コントロー ルである。ウィンドウのサイズは、<Windows>要素に Width 属性および Height 属性を用いて明示的 に指定するほかに、SizeToContent 属性を用いてコンテンツのサイズに合わせることも可能である。 SizeToContent 属性に WidthAndHeight を指定することで、タイトルバーや枠線の太さを気にするこ となく、コンテンツのサイズをぴったり指定できる。 ウィンドウでは、以下のような属性を指定することで、ウィンドウの見た目や機能をいろいろとカスタ マイズ可能である。 ・WindowStyle: タイトルなしのウィンドウや、ダイアログ形式(=固定サイズ)のウィンドウを作れ る。 ・ResizeMode: リサイズ可能かどうかを指定する。 ・AllowsTransparency: ウィンドウの背景色を半透明にする際に、背後のウィンドウやデスクトップが 透けて見えるようにするためにはAllowsTransparency 属性に True を設定する必要がある。 例えば、List 3 に示すような XAML コードで、枠線なし、リサイズ可能、半透明のウィンドウを作る ことができる。Figure 8 に実行結果を示す。 <Window x:Class="atmarkit08.NoneStyleWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" WindowStyle="None" ResizeMode="CanResizeWithGrip" AllowsTransparency="True" Background="#80808080" SizeToContent="WidthAndHeight"> <Grid> <TextBlock FontSize="50">半透明ウィンドウ</TextBlock> </Grid> </Window> List 3: 枠線なし、リサイズ可能、半透明のウィンドウ Figure 8 : List 3 の実行結果 ※ この場合、ウィンドウの背後に Visual Studio の C#コード・エディターが表示されている。 このようなウィンドウを作った場合、タイトルバーが存在しないため、そのままではドラッグによるウ

(30)

ィンドウの移動ができない。ウィンドウの移動を可能にしたければ、以下のように、マウス・クリック・ イベントのハンドラにDragMove メソッドを呼び出すコードを記述する(C#の例)。

Visual Basic Visual C#

this.MouseLeftButtonDown += (sender, e) => { this.DragMove(); };

ウィンドウを閉じるのも、コンテキスト・メニューやキー入力イベントなどを使うといいだろう。例え ば以下のようなコードで(C#の例)、任意のキーが入力されたときにウィンドウを閉じるようにできる。

Visual Basic Visual C#

this.KeyDown += (sender, e) => { this.Close(); };

用途:ユーザーとの対話 ○ボタン Table 3 にボタンに関連する UI 要素を示す。 UI 要素 説明 ButtonBase ボタンの共通基底 Button 通常のボタン ToggleButton CheckBox コントロールなどの、オン/オフを切り替えられるコントロールの基底 クラス Table 3: ボタン要素 前 節 で 、 レ イ ア ウ ト 部 品 と し て 紹 介 し た RepeatButton コ ン ト ロ ー ル も ButtonBase ク ラ ス (System.Windows.Controls.Primitives 名前空間)から派生している。

ButtonBase クラスの ClickMode プロパティを設定することで、Click イベントが発生するタイミング を「Release」(=ボタンを押して離したとき)、「Press」(=ボタンを押したとき)、「Hover」(=ボタ ンの上にマウス・カーソルを載せたとき)の3 つの中から選べる。

また、Button クラスでは、IsDefault プロパティに「true」を設定することで、いわゆるデフォルト・ ボタン(=Windows フォームでいうところの AcceptButton。[Enter]キーを押したときに Click イベ ントが発生する)に、IsCancel プロパティに「true」を設定することでキャンセル・ボタン(=同、 CancelButton。[Escape]キーを押したときに Click イベントが発生する)にすることができる。

ToggleButton クラス(System.Windows.Controls.Primitives 名前空間)は、オン/オフの 2 つの状態 を表すクラスであるが、IsThreeState プロパティが true の場合、オン/オフ/未設定の 3 つの状態(= IsChecked プロパティが false のときと null のときで異なる表示が行われる)を表すことも可能である。

(31)

Table 4 にテキスト入力に関連する UI 要素を示す。 UI 要素 説明 TextBox 通常のテキストボックス RichTextBox リッチ・テキストを編集するためのテキストボックス PasswordBox パスワード用のテキストボックス。入力された文字列は伏せ字で表示され、内部的に暗号化される Table 4: テキスト入力要素 <TextBox>要素および<RichTextBox>要素では、テキストボックス内で選択されている文字列に関する 情報を、SelectionStart プロパティ、SelectionLength プロパティ、および、SelectedText プロパティ を通して取得できる。また、AutoWordSelection プロパティに「true」を設定することで、マウスでド ラッグした際に単語単位で文字列選択されるよう、選択範囲が自動調整されるようになる。 <TextBox>要素内で複数行のテキストを表示したい場合には、TextWrapping プロパティに「Wrap」を 設定する。複数行テキストを表示する際、MinLines プロパティおよび MaxLines プロパティを設定し ておくと、実際の行数が変わる場合にも表示上のサイズを固定することができる。また、[Enter]キー で改行を入力したい場合には、AcceptsReturn プロパティに「true」を設定する。 ま た 、WPF に は ス ペ ル チ ェ ッ ク 機 能 が あ り 、 <TextBox> 要 素 や <RichTextBox> 要 素 の SpellCheck.IsEnabled 添付プロパティに「true」を設定することで、スペルチェックが働くようになる。 【コラム】UI 要素上の文字がにじんで見える場合の対処法(WPF 4 以降) WPF アプリケーションでは、UI 要素の位置などを浮動小数点精度で計算し、非整数ドットになった 場合には補間処理を行っている。この挙動は、アニメーション時に滑らかな表示ができるという利点 はあるものの、動きがない場合でフォント・サイズが小さいときに文字がにじんで見えるという問題 があった。 そこで、WPF 4 では、TextOptions クラス(System.Windows.Media 名前空間)で定義された添付 プロパティを用いて、アニメーションの有無をヒントとして与えたり、ClearType フォント表示を行 うかどうかを指定したりすることで文字の描画方法を制御できるようになった。 ○そのほかの対話要素 Table 5 にそのほかの対話的 UI 要素を示す。 分類 UI 要素 説明 データ DataGrid グリッド状にデータを表示・編集 Calendar カレンダ DatePicker 日付を選択 選択 CheckBox チェックボックス RadioButton ラジオボタン。パネル内では1 つだけがチェック可能*1

(32)

ComboBox コンボボックス。いわゆるドロップダウン形式で項目を選択 する ListBox リストボックス TreeView ツリー形式で項目を表示・選択する Slider つまみをスクロールすることで値を変化させる メニュー Menu メニュー ContextMenu 右クリックで表示するコンテキスト・メニュー ToolBar ツールバー 情報表示 TextBlock テキストを表示 Label テキストボックスなどに付けるラベル。ショートカット・キーを設定可能 ToolTip マウス・カーソルを重ねたときにポップアップ表示されるツ ールチップ*2 Popup ポップアップ。ツールチップと異なり、表示/非表示の切り 替えはIsOpen プロパティを用いて明示的に行う ProgressBar 処理の進捗(しんちょく)状況を表示する StatusBar ステータスバー ナビゲーション NavigationWindow 「戻る」「進む」などの機能を有するウィンドウ Frame ページを格納するためのフレーム Page ページ Hyperlink ページを遷移するためのリンク Table 5: そのほかの対話的 UI 要素 *1 <RadioBox>要素は、GroupName プロパティを指定することでグループ化できる。同一のグループ 内でチェックできるのは1 つだけとなる。特に GroupName プロパティを指定しなかった場合には、同 一のパネル(=Panel クラスを継承する<Grid>などの要素)内でグループ化される。 *2 ツールチップでは、ToolTipService クラス(System.Windows.Controls 名前空間)で定義された添 付プロパティを用いて、表示する位置や時間などの設定が行える。 用途:そのほか Table 6 にそのほかのコントロールや関連する UI 要素を示す。 分類 UI 要素 説明 メディア Image 画像を表示する MediaElement 動画などを表示する ドキュメント DocumentViewer FlowDocumentPageViewer FlowDocumentReader ドキュメント表示

(33)

FlowDocumentScrollViewer StickyNoteControl 付せんのように、付帯情報を表示する デジタル・インク InkCanvas マウス、タッチ、スタイラスなどの操作でストロー クを描画するための領域 Table 6: そのほかのコントロールや関連する UI 要素 次回は基本図形や2D 描画など、グラフィック関係について説明していく。 ■ 第9 回 WPF の「グラフィックス」を学ぼう ■ 第1 回で説明したように、WPF では、コントロール、メディア、文書など、さまざまな UI 要素を統一 的に扱うことができる。メディアだけを見ても、ビットマップ画像、ベクタ・グラフィックス、3D グ ラフィックスなど、さまざまなメディアを対象としている。 今回は、このようなメディア関連のUI 要素と、ブラシ、変形、ビットマップ効果などグラフィックス に関連する項目について説明していく。 ■ メディア関連要素 WPF では、以下のようなメディアを統一的に取り扱える。 ・ベクタ・グラフィックス(=幾何学図形) ・ビットマップ画像 ・動画/音声 ・グリフ(=文字の描画) ・3D グラフィックス 各メディアの話に入る前に、1 つ補足をしておこう。 補足:FrameworkElement 派生クラスと Drawing 派生クラス

WPF には、FrameworkElement クラス(System.Windows 名前空間)から派生するものと Drawing クラス(System.Windows.Media 名前空間)から派生するものの 2 系統のクラス群が存在する。 FrameworkElement クラスは、UI 要素として利用する分には非常に便利なレイアウトやスタイルなど の機能を有するが、これらの機能は単に描画を行いたいだけの場合には機能過多で、性能上の問題とな ることもある。そこで、レイアウトなどの機能を持たず、描画機能だけを提供する軽量にベクタ・グラ フィックスを描画するクラスとして提供されているのがDrawing クラスである。 Table 1 に示すように、3D グラフィックス以外は、FrameworkElement クラスから派生するものとほ ぼ1 対 1 に、Drawing クラスから派生するクラスが存在する。 FrameworkElement Drawing 幾何学図形 Shape GeometryDrawing 画像 Image ImageDrawing

(34)

FrameworkElement Drawing

動画/音声 MediaElement VideoDrawing

グリフ Glyphs GlyphRunDrawing

3D Viewport3D (なし)

Table 1: メディア関連の FrawemorkElement 派生クラスと Drawing 派生クラス

直接利用する機会が多いのはFrameworkElement から派生する側のクラス群だろう。一方で、Drawing クラスは以下のクラスで利用する。 ・DrawingImage クラス: Drawing オブジェクトを画像として利用。 ・DrawingBrush クラス: Drawing オブジェクトをブラシ(背景の塗りつぶしなど)として利用。 ・DrawingVisual クラス: 軽量な Visual オブジェクト(=WPF の UI 要素の共通基底クラスのオブ ジェクト)を生成する。

また、Drawing クラスは Freezable クラス(第 7 回のコラム参照)から派生しているため、固定化(frozen) してあればマルチスレッドで利用可能である。グラフィックス関係のオブジェクトを複数のスレッドか ら参照するなら、Drawing クラスを使う必要がある。 差し当たって、「Drawing クラスから派生するクラス群は高速な描画が必要な際に使う」とだけ覚えて おけばいいだろう。以下の各メディアの解説では、利用頻度の高いFrameworkElement クラスから派 生するUI 要素についてのみ説明する。 メディア:幾何学図形(=ベクタ・グラフィックス) Shape クラス(System.Windows.Shapes 名前空間)から派生する UI 要素によって、四角形(=矩形) やだ円などの幾何学図形を描画できる(以下、これらの UI 要素を総称して「Shape 要素」と呼ぶ)。 WPF ではこれらの幾何学図形はベクタ・グラフィックスとして描画されるため、Figure 1 に示すよう に、拡大しても荒くならない。

(35)

Figure 1: Shape 要素の拡大 ※ この例では、<Ellipse>(だ円)要素を 2/5/10/30 倍に拡大している。 Shape 要素には以下のような UI 要素が存在する(いずれも System.Windows.Shapes 名前空間)。 ・Rectangle: 四角形を描画する。角の丸い四角形も描画可能。 ・Ellipse: だ円を描画する。 ・Line: 2 点間をつなぐ線分を描画する。 ・Polygon: 与えられた複数の頂点をつなぐ多角形を描画する。 ・Polyline: 与えられた複数の頂点をつなぐ折れ線を描画する。 ・Path: 後述する「ジオメトリ」を使って任意の幾何学図形を描画する。 注意点として、<Rectangle>要素や<Ellipse>要素では、斜め向きの図形は作れない(辺や長軸/短軸が x 軸/y 軸と平行なものだけを作れる)。斜め向きにしたければ、さらに、後述する変形(= RenderTransform プロパティなど)を用いて回転処理を掛ける。 ○塗りつぶしと枠線 すべてのShape 要素に共通して、塗りつぶしと枠線の描画方法を設定できる。Fill プロパティによって 塗りつぶしに使うブラシを、Stroke プロパティによって枠線に使うブラシを指定する。また、 StrokeThickness プロパティのように、Stroke から始まるいくつかのプロパティを用いて枠線の表示方 法を変更できる。枠線の変更の例をMovie 1 に示す。 https://www.youtube.com/watch?v=WsU_5mjvxQs&feature=player_embedded Movie 1: Shape 要素の枠線の設定 ○<Polyline>要素/<Polygon>要素の塗りつぶし判定 <Polyline>要素および<Polygon>要素では、線の引き方によっては図形の内側/外側(=塗りつぶすべ き領域かどうか)の判定に迷う場合がある。以下のような XAML コードによって描ける五芒星(ごぼ うせい)がその例の1 つとなる。

<Polygon Points="100 0 158 180 4 69 195 69 41 180" Stroke="Black" Fill="LightBlue" /> 五芒星(ごぼうせい)を描くXAML コード このような場合に、<Polyline>要素および<Polygon>要素には、FillRule というプロパティがあり、 Figure 2 に示すような判定方法が存在する。ある点を始点として半直線を伸ばしたときに、図形の枠線 とその半直線が何回交わっているかによって図形の内側/外側を判定する。FillRule プロパティが 「EvenOdd」の場合には交点が奇数のときだけを、「NoneZero」の場合には 0 回以上のときを内側と見 なす。

Figure 3: Canvas の実行例
Figure 4: ItemsControl クラスの内部構造
Table 4 にテキスト入力に関連する UI 要素を示す。  UI 要素  説明  TextBox  通常のテキストボックス  RichTextBox  リッチ・テキストを編集するためのテキストボックス  PasswordBox  パスワード用のテキストボックス。入力された文字列は伏せ字で表示され、内部的 に暗号化される  Table 4:  テキスト入力要素  &lt;TextBox&gt;要素および&lt;RichTextBox&gt;要素では、テキストボックス内で選択されている文字列に関する 情報を
Table 1:  メディア関連の FrawemorkElement 派生クラスと Drawing 派生クラス
+3

参照

関連したドキュメント

にする。 前掲の資料からも窺えるように、農民は白巾(白い鉢巻)をしめ、

化し、次期の需給関係が逆転する。 宇野学派の 「労働力価値上昇による利潤率低下」

本時は、「どのクラスが一番、テスト前の学習を頑張ったか」という課題を解決する際、その判断の根

 映画「Time Sick」は主人公の高校生ら が、子どものころに比べ、時間があっという間

またこの扇状地上にある昔からの集落の名前には、「森島」、「中島」、「舟場

② 入力にあたっては、氏名カナ(半角、姓と名の間も半角で1マス空け) 、氏名漢 字(全角、姓と名の間も全角で1マス空け)、生年月日(大正は

ハイデガーは,ここにある「天空を仰ぎ見る」から,天空と大地の間を測るということ

ところで,労働者派遣契約のもとで派遣料金と引き換えに派遣元が派遣先に販売するものは何だ