UWP用のデザインツール Fluent XAML Theme Editor を使ってWinUI3アプリのテーマ色を設定する

WInUI3関連記事

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

やりたいこと

Windowsの「色」の設定で、「ライト」「ダーク」が選択できる。

f:id:tera1707:20220311224208p:plain

これを切り替えると、例えば設定画面も、下記のように白黒に切り替わる。

f:id:tera1707:20220311224615p:plainf:id:tera1707:20220311224553p:plain

この設定に、自分でつくるWinUI3のアプリもついていくようにしたい。
(ライト/ダーク切り替えで、ライト/ダークになるようにしたい)

※WinUI3のアプリは、なにもしなくてもライト/ダーク切り替えると、こんな感じで、それなりにライト/ダークな見た目になるっぽい。

f:id:tera1707:20220311223500p:plainf:id:tera1707:20220311223535p:plain

ただここから、ちょっと自分の好きな色のライト/ダークな色にしたい。

やり方概要

UWPアプリ向けに、「Fluent XAML Theme Editor 」という、ライト/ダークテーマ対応のためのResourceDictionaryのコード作成ツールがあった。

github.com

Microsoft Storeからもダウンロードできる。

また、その使い方の説明が、MSの開発者ブログにあった。

blogs.windows.com

その開発者ブログを参考に、ライト/ダークに対応させる。

やり方詳細

まず、Fluent XAML Theme Editor で、ライト/ダークごとに、自分の好きな色に設定する。(ツール自体の使い方は、ツールの説明ページを参照)

最初は白!黒!という感じの色になっているが、今回は下記のようにしてみる。

f:id:tera1707:20220311230712p:plain

好きな色にしたら「Export」ボタンを押す。押すと、ResourceDictionaryのコードが別Windowで出てくるので、それをコピーする。 (どうやら、コード中の<ResourceDictionary x:Key="Default">がダークテーマ、<ResourceDictionary x:Key="Light">がライトテーマのリソースを書いている部分っぽい。<ResourceDictionary x:Key="HighContrast">は、ハイコントラストをONにしたときの定義なのかも)

次に、
WinUI3のプロジェクトに、WinUI3の「リソースディクショナリ」を追加する。

f:id:tera1707:20220311230946p:plain

それで作成されたResourceDictionaryのxamlファイルに、先ほどツールがExportしたコードを貼り付ける。 (元のコードは全消しして、Exportしたものを貼り付ける)

そうすると、2022/03月の時点では、下記のようなエラーが出た。

f:id:tera1707:20220311231216p:plain

RevealBackgroundBrushは、WinUI3では使えないっぽい。(下記参照)
https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.media.revealbackgroundbrush?view=winrt-20348
https://github.com/microsoft/microsoft-ui-xaml/issues/5210

AcrylicBrushBackgroundSourceが無いと言っているのはなぜかは分からないが、現時点では「WinUI3はAcrylic対応していない、近日対応予定」みたいな記事をどこかで見たので、その関係でWinUI3では今は使えないのかも。

なので、今回は下記をした。

  • AcrylicBrushBackgroundSource の値を入れてる部分を削除(2か所)
  • RevealBackgroundBrushの定義部分を削除

これで、リソースディクショナリのファイルは完成。(今回はデフォの名前そのままでResourceDictionary1.xaml)
次に、これをアプリに適用する。

WinUI3プロジェクトの中のApp.xamlを開くと、‘‘と書いてある部分があるので、そこに作ったResourceDictionary1.xamlを入れる。下記のようにする。

<Application
    x:Class="ThemeJikken.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:ThemeJikken">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
                <!-- Other merged dictionaries here -->
                <!-- ★コレ↓を入れた★ -->
                <ResourceDictionary Source="ResourceDictionary1.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <!-- Other app resources here -->
        </ResourceDictionary>
    </Application.Resources>
</Application>

※もし、ResourceDictionary1.xamlを、ソリューションエクスプローラー上でxamlと同じ階層に置いているのではなく例えば「ResourceDictionary」フォルダの中に入れていたりした場合は、下記のように書くこと。

<ResourceDictionary Source="ResourceDictionary/ResourceDictionary1.xaml"/>

これで、テーマごとのリソースディクショナリの設定完了。動かしてみると、下記のようになる。

f:id:tera1707:20220311232721p:plainf:id:tera1707:20220311232737p:plain

背景だけ、デフォルトのライト/ダーク配色になっている。 Fluent xaml Theme Editorの説明ページによると、最後に、ページの背景色を、テーマに選択したRegionColorに設定することを忘れないでください。自動的に設定されない唯一のブラシです。とのこと。

どうやら、RegionBrushだけは、自分で設定しないといけない様子。

アプリの中の、表示しているWindowやPageの一番外側のGridなどの要素に対して、Background="{ThemeResource RegionBrush}"を設定してやる。

そうすると、下記のように、背景もFluent XAML Theme Editorで作った色と同じになってくれる。

f:id:tera1707:20220311233500p:plainf:id:tera1707:20220311233447p:plain

備考

作ったアプリを起動して、ハイコントラストONにしてみた。

f:id:tera1707:20220311223659p:plain

うーん、ボタンのところがなんか変?ハイコントラスト時は少々改良必要なのかも。(別途調べようと思う)

220414追記

ダーク、ライトモード時の色に加えて、ハイコントラスト時の色を調整する方法も下記で調べた。

tera1707.com

上記でいろいろ調べてる中で分かってきたのは、

Fluent XAML Theme Editor で出力したリソースディクショナリのxamlは、不要なものもたくさん記述されており、 そのままWinUI3に適用すると、変な動きをしてしまうこともあるっぽい。(詳細までは調べられていない)

なので、今の時点では、Fluent XAML Theme Editor で出力したリソースディクショナリは使ってもいいが、不要な部分は削除して使う方がよいかと思った。(今のところこうしたらよいな、と思うやり方は、上の記事に書いたので参照ください)

参考

Fluent XAML Theme Editor

https://github.com/Microsoft/fluent-xaml-theme-editor

C++xamlでFluent xaml Theme Editorで作ったResourceDictionaryを使おうとしている。
同じやり方がC#xamlでもできた。

https://github.com/microsoft/microsoft-ui-xaml/issues/5210

Windows開発者ブログ
Fluent xaml Theme Editorがやさしめに書かれている。

https://blogs.windows.com/windowsdeveloper/2018/10/10/fluent-xaml-theme-editor-preview-released/