Windows GUIプログラミング入門7 システムカラー、画面レイアウト(3)

# ■はじめに
今回は、システムカラーの一覧を2種類のレイアウトで表示してみます。
複数のコントロールに共通のスタイルを適用する方法もやります。

![wbg7-00.png](https://qiita-image-store.s3.amazonaws.com/0/142879/9b80ff53-f935-aec0-de3d-4c1b5e7c733f.png)

キーワード：SystemColors, TabControl, ScrollViewer, WrapPanel, Style, region

[注意]
これまでの回で説明済みの操作方法等は、説明を省略したり簡略化している場合があります。

# ■開発環境
* Windows 10
* Visual Studio Community 2015 Update 3
* .NET Framework 4.x

# ■作ってみる

## ◇TabControl

ツールボックスから「TabControl」を画面デザイナのGridにドラッグ＆ドロップします。
![wbg7-01.png](https://qiita-image-store.s3.amazonaws.com/0/142879/e72266a9-e2be-0f91-5a6a-ae3b749d4570.png)

ドキュメントアウトラインでTabControlを右クリックし、「レイアウト」 - 「すべてリセット」を選択します。
![wbg7-02.png](https://qiita-image-store.s3.amazonaws.com/0/142879/456a8aa1-4e20-bae0-88bf-ce64d5720f0e.png)

`TabItem`の`Header`プロパティを`Stackパネル`、`Wrapパネル`に書き換えます。
これはタブのテキスト部分になります。
`Window`の`ResizeMode`を`CanResizeWithGrip`に設定します。
![wbg7-03.png](https://qiita-image-store.s3.amazonaws.com/0/142879/691a4bdc-0918-49a2-f155-497d2c54c4c9.png)

## ◇ScrollViewer

1つ目のタブの中にある`Grid`を右クリックし、「レイアウトの種類の変更」 - 「ScrollViewr」を選択します。
![wbg7-04.png](https://qiita-image-store.s3.amazonaws.com/0/142879/40c92b2c-4580-a042-8939-4a5846d73907.png)

`ScrollViewer`の上に`StackPanel`をドラッグ＆ドロップします。
更にその`StackPanel`の上に`TextBlock`をドラッグ＆ドロップします。
![wbg7-05.png](https://qiita-image-store.s3.amazonaws.com/0/142879/c629094a-f933-7acd-5f87-fb6aa5b6b843.png)

`TabControl`同様、`StackPanel`のサイズもリセットしてください。
画面デザイナ上ではこのように表示されるはずです。
![wbg7-06.png](https://qiita-image-store.s3.amazonaws.com/0/142879/b2622f07-da61-a776-ba7c-732beec85857.png)
ScrollViewrを使うことで、画面に表示しきれないほどコントロールがある場合、スクロールして表示できるようになります。

## ◇WrapPanel

次にもう一つのタブの方を編集していきます。
`Grid`を右クリックし、「レイアウトの種類の変更」 - 「WrapPanel」を選択します。
![wbg7-07.png](https://qiita-image-store.s3.amazonaws.com/0/142879/6b866694-355f-3f95-bb0b-4d86ba1ae418.png)
（ScrollViewerを使わない場合）画面からあふれたコントロールは表示されないStackPanelとは違い、WrapPanelはあふれそうになったら次の行または列に配置しようとします。
このコントロールも`Orientation`プロパティがあって縦並び・横並びを選択できます。
サンプルでは既定値の横並び（`Horizontal`）のままで使用します。

同じようにTextBlockを配置します。
ここまででXamlのコンテンツは以下のようになっているはずです。

```Xml
<Grid>
    <TabControl x:Name="tabControl">
        <TabItem Header="Stackパネル">
            <ScrollViewer Background="#FFE5E5E5">
                <StackPanel>
                    <TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="TextBlock"/>
                </StackPanel>
            </ScrollViewer>
        </TabItem>
        <TabItem Header="Wrapパネル">
            <WrapPanel Background="#FFE5E5E5">
                <TextBlock x:Name="textBlock1" TextWrapping="Wrap" Text="TextBlock"/>
            </WrapPanel>
        </TabItem>
    </TabControl>
</Grid>
```
## ◇SystemColors

1つ目のタブ内のTextBlockから`x:Name`, `TextWrapping`を削除し、
プロパティウィンドウの「ブラシ」カテゴリ、`Background`プロパティを選択、一番右端の「ブラシリソース」タブを選択、「システムBrushリソース」の一覧から適当に何か選択します。
![wbg7-08.png](https://qiita-image-store.s3.amazonaws.com/0/142879/5ed83f17-26a1-d089-b5bc-4451af179680.png)

そうすると、以下のような感じで`Background`プロパティが設定されます。

```Xml
<TextBlock Text="TextBlock" Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
```

TextBlockの上下を#region～#endregionで挟みます。

![wbg7-09.png](https://qiita-image-store.s3.amazonaws.com/0/142879/e9a7b5a3-bdd8-b46b-9178-f439d7a50297.png)

このTextBlock定義を元に編集・コピペしながら以下のように入力します。

```Xml
<StackPanel>
    <!--#region テキスト定義1 -->

    <TextBlock Text="アクティブなウィンドウの境界線の色" Background="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"/>
    <TextBlock Text="アクティブなタイトルバーの背景色" Background="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}"/>
    <TextBlock Text="アクティブなウィンドウのタイトル バーのテキストの色" Background="{DynamicResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}" Foreground="White"/>
    <TextBlock Text="アプリケーション ワークスペースの色" Background="{DynamicResource {x:Static SystemColors.AppWorkspaceBrushKey}}"/>
    <TextBlock Text="3D 表示要素の表面の色" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
    <TextBlock Text="3D 表示要素の影の色" Background="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}"/>
    <TextBlock Text="3 次元表示要素の暗いシャドウの色" Background="{DynamicResource {x:Static SystemColors.ControlDarkDarkBrushKey}}" Foreground="White"/>
    <TextBlock Text="3 次元の表示要素のライト色" Background="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}"/>
    <TextBlock Text="3 次元表示要素の強調表示の色" Background="{DynamicResource {x:Static SystemColors.ControlLightLightBrushKey}}"/>
    <TextBlock Text="3 次元表示要素のテキストの色" Background="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" Foreground="White"/>
    <TextBlock Text="デスクトップの色" Background="{DynamicResource {x:Static SystemColors.DesktopBrushKey}}" Foreground="White"/>
    <TextBlock Text="アクティブなウィンドウのタイトル バーのグラデーションの右側の色" Background="{DynamicResource {x:Static SystemColors.GradientActiveCaptionBrushKey}}"/>
    <TextBlock Text="非アクティブなウィンドウのタイトル バーのグラデーションの右側の色" Background="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionBrushKey}}"/>
    <TextBlock Text="使用できないテキストの色" Background="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" Foreground="White"/>
    <TextBlock Text="選択した項目の背景色" Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
    <TextBlock Text="選択した項目のテキストの色" Background="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>

    <!--#endregion-->
</StackPanel>
```

画面デザイナではこのように表示されます。
※システムで設定された色を表示しているので、ご利用の環境によってはこの通りの色にならない可能性があります。
![wbg7-10.png](https://qiita-image-store.s3.amazonaws.com/0/142879/333934e7-521b-4390-012e-33994f17a52e.png)

## ◇共通スタイルの設定

HTMLで使うCSSのように、複数の項目に一括で設定を適用しましょう。
1つ目のタブ内のStackPanelの中に`StackPanel.Resources`タグを入力し、その中に`Style`タグを定義します。

```Xml
<StackPanel>
    <StackPanel.Resources>
        <!-- StackPanel用 テキストの既定スタイル -->
        <Style TargetType="TextBlock">
            <!-- コントロール間の余白 -->
            <Setter Property="Margin" Value="2,2,2,0"/>
        </Style>
    </StackPanel.Resources>
    :
    :
```

`TargetType`に適用対象のコントロールの型を、`Property`に設定するプロパティ名、`Value`に設定値を指定します。

※`Margin`プロパティの指定方法のバリエーションは、 [こちらの記事](http://qiita.com/Kosen-amai/items/75136edba4f8ef90d26f "Xamlメモ　Marginプロパティ - Qiita") 参照。

これでこのStackPanel内にあるTextBlockに`Margin`プロパティが一括で設定され、テキスト間に少し余白が空きました。
![wbg7-11.png](https://qiita-image-store.s3.amazonaws.com/0/142879/3fd658fa-8e1e-44d3-f69e-63109ac422e8.png)

2つ目のタブも同じ感じで以下のように入力します。

```Xml
<TabItem Header="Wrapパネル">
    <WrapPanel Background="#FFE5E5E5">
        <WrapPanel.Resources>
            <!-- WrapPanel用 テキストの既定スタイル -->
            <Style TargetType="TextBlock">
                <!-- コントロール間の余白 -->
                <Setter Property="Margin" Value="2"/>
                <!-- コントロール内の余白 -->
                <Setter Property="Padding" Value="5,10"/>
            </Style>
        </WrapPanel.Resources>

        <!--#region テキスト定義2 -->

        <TextBlock Text="フォーカスされている項目の指定に使用する色" Background="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}" Foreground="White"/>
        <TextBlock Text="非アクティブなウィンドウの境界線の色" Background="{DynamicResource {x:Static SystemColors.InactiveBorderBrushKey}}"/>
        <TextBlock Text="アクティブでないウィンドウのタイトル バーの背景色" Background="{DynamicResource {x:Static SystemColors.InactiveCaptionBrushKey}}"/>
        <TextBlock Text="非アクティブなウィンドウのタイトル バーのテキストの色" Background="{DynamicResource {x:Static SystemColors.InactiveCaptionTextBrushKey}}" Foreground="White"/>
        <TextBlock Text="非アクティブな選択項目を強調表示するために使用される色" Background="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
        <TextBlock Text="非アクティブな選択項目のテキストの色" Background="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}" Foreground="White"/>
        <TextBlock Text="ToolTip コントロールの背景色" Background="{DynamicResource {x:Static SystemColors.InfoBrushKey}}"/>
        <TextBlock Text="ToolTip コントロールのテキストの色" Background="{DynamicResource {x:Static SystemColors.InfoTextBrushKey}}" Foreground="White"/>
        <TextBlock Text="メニュー バーの背景色" Background="{DynamicResource {x:Static SystemColors.MenuBarBrushKey}}"/>
        <TextBlock Text="メニューの背景色" Background="{DynamicResource {x:Static SystemColors.MenuBrushKey}}"/>
        <TextBlock Text="メニュー項目の強調表示に使用する色" Background="{DynamicResource {x:Static SystemColors.MenuHighlightBrushKey}}"/>
        <TextBlock Text="メニューのテキストの色" Background="{DynamicResource {x:Static SystemColors.MenuTextBrushKey}}" Foreground="White"/>
        <TextBlock Text="スクロール バーの背景色" Background="{DynamicResource {x:Static SystemColors.ScrollBarBrushKey}}"/>
        <TextBlock Text="ウィンドウのクライアント領域の背景色" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
        <TextBlock Text="ウィンドウ フレームの色" Background="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" Foreground="White"/>
        <TextBlock Text="ウィンドウのクライアント領域のテキストの色" Background="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" Foreground="White"/>

        <!--#endregion -->

    </WrapPanel>
</TabItem>
```

今度は`Margin`の他に`Padding`プロパティもスタイルに設定しています。
Paddingはコントロールの中の余白です。指定方法はMarginと同じです。
![wbg7-11_2.png](https://qiita-image-store.s3.amazonaws.com/0/142879/c3d75d82-831a-de80-49c2-3759fa9b941f.png)

![wbg7-12.png](https://qiita-image-store.s3.amazonaws.com/0/142879/65bfe52d-ffbc-53bf-d59f-11d82005c147.png)

スタイルを画面全体で利用したい場合、
`Window.Resources`タグを作って、その中にスタイルを定義します。

```Xml
<Window x:Class="XXXXXXX.XXXXXX"
        :
        :>
    <Window.Resources>
        <!-- 画面内共通スタイル -->
        <Style xxxx>
            :
        </Style>
    </Window.Resources>

    <Grid>
        :
    </Grid>
</Window>
```

複数の画面で使うような全体的なスタイルは、
`App.xaml`内の`Application.Resources`の中に定義します。

## ◇regionによる折り畳み

regionコメントで囲まれた範囲は、左端の`[-]`をクリックすることで折り畳むことができます。
開始タグ～終了タグとは別の単位でまとめたい場合など、うまく使うとXamlの見通しが良くなります。
![wbg7-13.png](https://qiita-image-store.s3.amazonaws.com/0/142879/35752af0-d24a-2f6f-a16b-0004246c9de4.png)


# ■動かしてみる

まずは「Stackパネル」タブの内容。
スクロールバーが表示されています。
![wbg7-14.png](https://qiita-image-store.s3.amazonaws.com/0/142879/fca36618-3088-b6a5-13da-f8b48a8c6e23.png)

画面を縦に伸ばして全部表示するとスクロールバーが無効表示になりました。
![wbg7-14_2.png](https://qiita-image-store.s3.amazonaws.com/0/142879/1cf5be98-70cc-ab5a-8a72-4697e15e5acd.png)

「Wrapパネル」タブを選択します。
![wbg7-15.png](https://qiita-image-store.s3.amazonaws.com/0/142879/6eb40ae3-a5b4-5df2-908a-6465cf697c73.png)

画面の横幅を広げてみると、上から順に右に向かって配置されていき、入らない場合は次の行に配置されるのがわかります。
![wbg7-15_2.png](https://qiita-image-store.s3.amazonaws.com/0/142879/ae3eb0ba-a268-95f9-7929-538a668e59ad.png)

おしまい

---

# ■参考サイト

* [SystemColors クラス - MSDN](https://msdn.microsoft.com/ja-jp/library/system.windows.systemcolors.aspx)

---

[＜＜ 最初の記事](http://qiita.com/Kosen-amai/items/f9e3df2aa80363f5af5b "Windows GUIプログラミング入門1 メッセージボックス表示") 　 [＜ 前の記事](http://qiita.com/Kosen-amai/items/9f5e56e8c80b348b127f "Windows GUIプログラミング入門6 画面遷移(2)") 　 [次の記事 ＞](http://qiita.com/Kosen-amai/items/c06f4c89f636b781795a "Windows GUIプログラミング入門8 画像、ボタン")