コントロールのマウスオーバー時等の色を変えたい

WInUI3関連記事

https://tera1707.com/entry/2022/02/06/144447#WinUI3

やりたいこと

WinUI3 各コントロールの見た目の色をいじりたい。

例えば、ボタンのマウスオーバー時の色を自分の好きな色に変えたい。
そのやり方を調べたときに辿った道順をメモする。

色の出どころがどこなのか?調べる

まずは、ボタンのマウスオーバー時の色がどこから来てるのか?を調べる。

C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAPに、Windowsのバージョンごとに、標準のResourceDictionaryがある。

おそらく、マウスオーバー時の色を変えたいくらいであれば、どのバージョンのResourceDictionraryを見ても同じなので、 一旦10.0.19041.0を開く。

その中の\10.0.19041.0\Generic\generic.xamlを開く。


★22/10/03追記

WinUI3の標準のResource、styleは上記ではなかった。
→こちらを参照
https://tera1707.com/entry/2022/10/02/235818


今回は、マウスオーバー時の色を変えたいだけなので、マウスオーバーの時の色変化は標準でどうやってるか?を見てみる。 →<VisualState x:Name="PointerOver">あたりを見る。

そうすると、そこには下記のようなことが書いてある。

  • BackgroundButtonBackgroundPointerOver にする
  • BorderBrushButtonBorderBrushPointerOver にする
  • ForegroundButtonForegroundPointerOver にする

例えばその中の ButtonBackgroundPointerOver(マウスオーバー時のボタンの背景の色) が実際何色かを見ていくと、

  • <StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SystemControlBackgroundBaseLowBrush" />とあり、
    • <SolidColorBrush x:Key="SystemControlBackgroundBaseLowBrush" Color="{ThemeResource SystemColorButtonFaceColor}" /> とある。

<StaticResource x:Key="ButtonBackgroundPointerOver" ResourceKey="SystemControlBackgroundBaseLowBrush" />はgeneric.xamlの中に3つあり、 それぞれ<ResourceDictionary x:Key="Default"><ResourceDictionary x:Key="HighContrast"><ResourceDictionary x:Key="Light">の中にある。 そのそれぞれが、ライト、ダーク、ハイコントラスト時の色の定義っぽい。

このSystemColorButtonFaceColorは、下記のシステムカラーの定義の中にあった。 C:\Program Files\Microsoft Visual Studio\2022\Community\DesignTools\SystemThemes\WinUI\SystemColors.xaml

私のVS2022がCommunityなので上記のフォルダだが、Professional版等、ほかのエディションだったらまた別のフォルダにあると思われる。

色は<Color x:Key="SystemColorButtonFaceColor">#FFF0F0F0</Color>とあった。

ここが、色の出所っぽい。

実際に色を変えてみる

じゃあその#FFF0F0F0を変えればいいのかなと思ったが、

SystemColorButtonFaceColorのようなSystemColors.xamlの中の色の定義は、自分のアプリのリソースではないので変えられなさそう。
SystemControlBackgroundBaseLowBrushは、それを使っている個所が多数あるので、変えることができたとしても変えたくない。

  • ButtonBackgroundPointerOverの色を上書きして、色を変えてみる。

まずは、簡易的に、メイン画面のリソースに、上書した色を書いてみる。
今回は、黄色にしてみた。

<Window
    x:Class="DefaultControlTemplateTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DefaultControlTemplateTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">   

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <StackPanel.Resources>
            <SolidColorBrush x:Key="ButtonBackgroundPointerOver" Color="Yellow" />
        </StackPanel.Resources>
        <Button x:Name="myButton" Click="myButton_Click">Click Me</Button>
    </StackPanel>
</Window>

これで、マウスオーバー時、

のような感じになった。

その後

あとは、そのほかのイベント(Disable時やボタン押下時)のときにも同じように、標準の色変化と違う色変化をしたければ、<VisualState x:Name="Pressed"><VisualState x:Name="Disabled">のときの色を上書してやればOK。

220411追記 SystemAccentColorLight1,2,3,SystemAccentColorDark1,2,3の正体

Fluent Xaml Theme Editorで作ったリソースディクショナリの中に、掲題のようなリソースがあったのだが、これがなんだかよくわかってなかった。
→下記に書いてあった。

docs.microsoft.com

Fluent Xaml Theme Editorの吐いたリソースディクショナリのコレ

を見て、勝手に「Lightとついてる奴は、ライトテーマを選んでいるときに、アクセントカラーとして使われる奴なんだろうな。(でも、<ResourceDictionary x:Key="Light">のなかにも‘#FF0064BE‘やDark2,Dark3があるな、どういう意味だろう?)となっていた。

これはそういう意味ではなく、

キー名 意味
SystemAccentColorDark3 SystemAccentColorよりとても暗い色
SystemAccentColorDark2 SystemAccentColorより暗い色
SystemAccentColorDark1 SystemAccentColorよりちょっと暗い色
SystemAccentColor 元のアクセントカラーの値
SystemAccentColorLight1 SystemAccentColorよりちょっと明るい色
SystemAccentColorLight2 SystemAccentColorより明るい色
SystemAccentColorLight3 SystemAccentColorとても明るい色

という意味らしい。だから、下記のようなxamlを書いて、

 <StackPanel Orientation="Horizontal">
     <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorDark3}"/>
     <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorDark2}"/>
     <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorDark1}"/>
     <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColor}"/>
     <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorLight1}"/>
     <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorLight2}"/>
     <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorLight3}"/>
 </StackPanel>

windowsのアクセントカラーの設定を青にしていると、

こうなる

緑にしてると

こうなる。

で、Fluent Xaml Theme Editorで作ったリソースディクショナリのように、自分のコードの中に‘#FF1D85D7‘などを書いていると、Windowsのアクセントカラー設定の色を上書きする形になり、Windowsのアクセントカラーの設定によらず、コードの中の上書した値が使われる形になる。

だから、アクセントカラーの色を使っているコントロールの色を、ユーザーのアクセントカラーの設定に左右されない色にしたいときは、これを上書き(オーバーライド)すればよいかも。
(もしくは、style等を使ってアクセントカラーを使うのをやめさせるか)

220411追記 {StaticResource 色のキー名} と {ThemeResource 色のキー名} の違い

StaticResource だと、起動時に一回だけリソースが読み込まれる。
ThemeResourceだと、テーマ変更時に再度読み込まれる。

docs.microsoft.com

ためしに、下記のようなxamlを書いてみる。

Dark1,2,3だけがStaticResourceを使っていて、SystemAccentColorとLight1,2,3がThemeResourceを使っている。

<StackPanel Orientation="Horizontal">
    <Grid Width="50" Height="50" Background="{StaticResource SystemAccentColorDark3}"/>
    <Grid Width="50" Height="50" Background="{StaticResource SystemAccentColorDark2}"/>
    <Grid Width="50" Height="50" Background="{StaticResource SystemAccentColorDark1}"/>
    <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColor}"/>
    <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorLight1}"/>
    <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorLight2}"/>
    <Grid Width="50" Height="50" Background="{ThemeResource SystemAccentColorLight3}"/>
</StackPanel>

これを、アクセントカラーで青色を選択した状態で、上記コードを起動すると下記のようになり、

そのままアプリ起動した状態でアクセントカラーを緑に変更すると、下図のようになる。 (Dark1,2,3の方が、OSのアクセントカラーの変更についてきていない)

220411追記 私と同じで、ブラシがたくさんありすぎて迷い込んだ方のissue

ブラシがたくさんありすぎてわけわからないので一覧が欲しい、とこの方も言っている様子。

github.com

まったく同じ気持ちだったのだが、ここで言われているのが、

  1. コントロールのテーマブラシとして名前の付いたブラシは1000を超える数がある。
  2. システムのブラシと色は約150〜200ある。
  3. ただし実際の色は、25種類前後だけ。

とのこと。

①が、C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP<sdkVersion>\10.0.19041.0\Generic\themeresources.xamlの2090行目より下にあるSliderContainerBackgroundのような、コントロールの種類名がキーについたブラシのことっぽい。

②が、themeresources.xamlの上の方にあるSystemなんとかかんとかというColorと、SystemControlなんとかかんとかという名前のSolidColorBrushっぽい。(10.0.22000.0のthemeresources.xamlの204~327行目あたり)

そのすぐ上あたりに、そのブラシで使っている色(Color)が定義されてる。(SystemAccentColorなど、特別な奴は、③の中にある)

③が、‘C:\Program Files\Microsoft Visual Studio\2022\Community\DesignTools\SystemThemes\WinUI\SystemColors.xaml‘ にある色とブラシのことっぽい。

220411追記 で、結局winui3でテーマ対応(ダーク、ライト、ハイコントラスト)対応するにはどうしたらいいのか?

考え中...

一番上に書いたやり方で、①をオーバーライドしてやれば、コントロールごとの色を変えることは可能だった。
では、もっと広い範囲の色を一気に変えたいとき等に、②③はオーバーライドできるのか?ためす。

参考

テーマの色を変えたいときのガイドライン。 デフォルトのリソースディクショナリがどこにあるか?や、色(をはじめとしたリソース)の変え方が書かれてる

docs.microsoft.com

SystemColorの定義が書かれていそうな個所を探していたときに見つけた WPFでの」 その辺がありそうなフォルダについて書かれた公式doc。 この辺をいろいろ見ていたら「winui」というフォルダがあり、そこを見たら、上で書いたフォルダが見つかった。
(WinUI3でSystemColorsの定義が書かれてそうなファイルについての公式docは見つけられなかった)

docs.microsoft.com

WinUI3のコントロールの見本市アプリ。

Microsoft Apps

参考書

WinUI3

WinUI3でアプリを作ろうと思ったときのとっかかりによかった。 msdocsに書いてある情報を、体系的に、順番に読みたいな、というときによいかも。(ただし英語)
この本で分からなかった、かゆいところに手が届かなかった部分を私は記事にしてる感じ。

C#①

表紙に書いてある通り、教科書として最適。 これからC#を勉強したいけど、ネットだけで勉強するのは効率が悪いから体系的に学べる本が欲しいときや、 ちょっとC#を勉強してコード書けるようになったけど、もう少し広く深く知りたいなというときによいと思う。
私は仕事で触れるコードを軸に、基本ネットで断片的にC#を学んだので、その知識の隙間を埋めて枝葉を広げるためにとても分かりやすかった。

C#②

C#の文法的に色々できるのは分かったが、いざ実装するときに、わかったことを使ってどう実装すればいいのか?と悩んだときに指針になりそうな本。
「プロパティ等の名前の付け方、どうすればいい?」「情報をクラス外部に見せるときに、プロパティにすべき?メソッドにすべき?」「異常だと判定したいとき、どんなときにどんな例外をスローすべき?」などなど、勉強になる部分が山ほどあった。
私のように「コードは書くけどこれであってるのか自信がない、レビューで指摘されるのが嫌だ、実装時の(心の)よりどころが欲しい」という人に最適。