![pexelskevinku577585 | Embarcadero RAD Studio Delphi C++Builder Blogs pexels kevin ku 577585](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/05/pexels-kevin-ku-577585-8035317-scaled.jpg?resize=1140%2C694&ssl=1)
この記事は、Embarcadero Delphi MVPであるIan Barker氏のブログの抄訳です
最新バージョンのMicrosoft Windowsは、間違いなく見た目にも美しくなっています。 アプリが灰色の厚板で、分厚いボタンのような見た目の時代は終わりました。 MicrosoftがFluent UIインターフェースを採用したことで、豊富なカラーパレット、すっきりとした無駄のない外観、Serifファミリのカールや、ねじれのないフォントが採用されました。さらにHighDPI、通知機能、「ライト」と「ダーク」の2つのモードに対応したテーマなど、最新のアプリケーションに必要なユーザビリティやユーザの利便性を考慮していました。
Table of Contents
アプリのHighDPI対応
RAD Studioでは、既にHighDPIに対応しています。 HighDPIの設定は、IDEのプロジェクトオプションで[アプリケーション] > [マニフェスト] > [DPIの認識]オプションで変更可能です(デフォルトは「ディスプレイごとのDPIに対応v2」に設定)。
HighDPIのオプションを有効すると、VCLランタイムの内部では、HighDPI(画面解像度のピクセル数)を理解し、それに対応するためのアセット情報やAPIに対する処理をWindowsへ通知します。VCLのHighDPIの対応は、実際にはVCL内部でかなり多くの処理が行われていますが、開発者はこのような内部処理を気にすることなくアプリを簡単にHighDPI化することができます。
HighDPIに対応していない古いバージョンのコンパイラでコンパイルされたプログラムを比較すると、高解像度のモニタでは少しぼやけて見えることがあります。 古いバージョンでは、マニフェストファイルの設定がなく、内部のAPIコールも古い「下位互換」のもので、最低限度の共通項で動作するため、結果的にアプリが最新のディスプレイ技術を最大限に活用できないためです。
これは例えると、1970年代の映画を4K有機ELテレビで見るようなもので、我慢はできますが、時代遅れに見えてしまいます。
最新のVCLでカバーされていないものは何ですか?
Windows 10によってもたらされた他の大きな目に見える変化は、「ダークモード」の導入でした。 何年もの間、私たちは、眩しさを和らげるために、白い背景、灰色のボタンなど、選択肢が少ない中でWindowsを実行してきました。その後、Microsoftは「ダークモード」を発表しました。 このダークモードは、その名の通り、すべてのWindowsのUIなどの外観を暗くするもので、Windows 10の設定メニューからモードを変更した場合は、アプリケーション側でそれを理解し、モード変更に対応する必要がありますが、VCLでは完全にカバーしていないエリアがあります。
Windowsのダークモードの検出
アプリの起動時には、Windowsが現在「ダークモード」または「ライトモード」のどちらを想定しているかを検出する必要があります。これは現在、一連のAPIコールによって処理されていますが、VCLでは現在サポートしていません。幸いなことに、レジストリキーをチェックすることができます。
本来であれば、Windows 10の設定メニューから「ダークモード」を変更した場合、Delphiアプリで「ダーク」であることを検出し、アプリ側で適切な「ダーク」テーマをロードするように指示する必要があります。同様に「ライトモード」に変更した場合は、Delphiアプリで適切な明るいVCLテーマをロードする必要があります。
VCLアプリのダークモードを簡単に検出する方法
上述しましたように現時点のVCLではサポートしていません。そこでWindowsのダークモードやライトモードを簡単に検出し、正しいテーマをロードするために、VCLのDelphiプログラムに含めることができる小さなユニットプログラムを作成しました。 もちろん、このコードは無償で利用可能なオープンソースなので自由に活用してください。
Delphiの素晴らしい点は、複雑な処理も少ないコーディングで実装できるところですね。
DelphiDarkModeユニットの入手方法
サンプルプログラムはGitHubリポジトリ経由で、以下のURLから入手できます。
https://github.com/checkdigits/delphidarkmode
上記のサンプルプロジェクトには、WindowsDarkMode.pasというファイル名のユニットが含まれています。
DelphiDarkModeユニットやWindowsダークモード全般については、CodeRageのブログ記事で詳しく紹介しています。
https://www.codedotshow.com/blog/coderage-2019-vcl-the-dark-side/
ここでは、プロジェクトマネージャでWindowsDarkMode.pasをプロジェクトに追加し、Windowsのダークモードを検出するコード例を紹介していきます。
Delphiのダークモードを使用して、Delphiのカスタムスタイルを自動的に変更する
まず必要なのは、2つのVCLカスタムテーマを選択してアプリに適用することです。
プロジェクトのオプションダイアログで「表示」を選択します。
ここでは、2つのVCLカスタムテーマにチェックを入れます。1つは「ライトモード」用、もう1つは「ダークモード」用です。 後ほど紹介するコートで必要になりますので、カスタムテーマの正確な名前を書き留めてください。
![modernizeyourappareyouhandlingwindowsthemescorrectlyja17953775 | Embarcadero RAD Studio Delphi C++Builder Blogs modernize your app are you handling windows themes correctly ja 1 7953775](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/05/modernize-your-app-are-you-handling-windows-themes-correctly-ja-1-7953775.png?resize=368%2C391&ssl=1)
Windows10
」と「Windows10 Dark
」を選択しています。 なお、GetItパッケージマネージャを使用して、プロがデザインした数多くのカスタムテーマをインストールして適用することができます。
また、Delphi Stylesの素晴らしいサイト(https://www.delphistyles.com/vcl/index.html)では、膨大な数のテーマが提供されています。
次に、自身のプログラムに以下のコードを追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// ... add to your form's definition private procedure HandleThemes; end; uses WindowsDarkMode; procedure TForm1.FormCreate(Sender: TObject); begin HandleThemes; end; procedure TForm1.HandleThemes; begin SetAppropriateThemeMode('Windows10 Dark', 'Windows10'); end; |
Windows10 Dark
」テーマを使用し、Windowsがライトモードに設定されている場合は、より明るい「Windows10
」テーマが使用されていることが確認できます。
これらの2つのテーマは、任意のテーマに置き換えることができます。ただし、注意が必要なのは、プロジェクトのオプションダイアログの「表示」セクションで、使用したい任意のカスタムテーマに選択し、予めチェックマークを付けておく必要があります。そして上記のコードのSetAppropriateThemeModeメソッドのパラメータを選択したカスタムテーマ名に置き換えてください。該当するカスタムテーマにチェックが付いていなかったり、SetAppropriateThemeModeメソッドのパラメータに該当するテーマと一致していないと、正しくテーマの適用は行われません。
アプリ実行中にWindowsがダークモードまたはライトモードに変更された場合の検出
では、アプリがすでに実行されていて、ユーザーがライトモードからダークモードに、またはその逆に変更した場合の対処はどうすれば良いでしょうか?
Windowsでは、実行中のアプリのトップレベルのWindowsすべてにWM_SETTINGSCHANGE
メッセージをブロードキャストします。このメッセージの’Section’パラメータは”ImmersiveColorSet
”です。WM_SETTINGSCHANGE
メッセージの到着をテストして、このパラメータを探せば、ユーザーがWindowsテーマをライトモードからダークモード、またはダークモードからライトモードに変更したことが判断できます。
Windowsのダーク/ライトモードの変更を検出するコードの追加
以下のコードをメインフォームの定義に追加します。
1 |
procedure WMSettingChange(var Message: TWMSettingChange); message WM_SETTINGCHANGE; |
続いて、実装セクションに以下のコードを追加します。
1 2 3 4 5 |
procedure TForm1.WMSettingChange(var Message: TWMSettingChange); begin if SameText('ImmersiveColorSet', String(Message.Section)) then HandleThemes; end; |
サンプルプログラムの実行例
下図は、Windowsテーマを切り替えた際にVCLアプリのテーマも一緒に変更するサンブルプログラムの実行例です。
![reacttotheme | Embarcadero RAD Studio Delphi C++Builder Blogs react to theme](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/05/react_to_theme-4363844.gif?resize=750%2C529&ssl=1)
Windowsのダーク/ライトモードの変更を検出する別の方法
RAD Studioでは一般的に、Windowsの設定変更メッセージを検出する方法は1つだけではありません。
例えば、TApplicationEvents
コントロールを使用することができ、 下図のようにOnSettingsChange
イベントハンドラを追加します。
![modernizeyourappareyouhandlingwindowsthemescorrectlyja29283766 | Embarcadero RAD Studio Delphi C++Builder Blogs modernize your app are you handling windows themes correctly ja 2 9283766](https://i0.wp.com/blogs.embarcadero.com/wp-content/uploads/2021/05/modernize-your-app-are-you-handling-windows-themes-correctly-ja-2-9283766.png?resize=433%2C317&ssl=1)
そして、イベントハンドラに以下のコードを追加します。
1 2 3 4 5 6 7 8 |
procedure TForm1.ApplicationEvents1SettingChange(Sender: TObject; Flag: Integer; const Section: string; var Result: Integer); begin if SameText('ImmersiveColorSet', String(Section)) then HandleThemes; end; |
WMSettingChange
メッセージをトラップする方が簡単です。
VCLアプリでWindowsダークモードを検出するための全コード
以下は、今回のブログで紹介した全体のサンブルコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
type TForm1 = class(TForm) Image1: TImage; procedure FormCreate(Sender: TObject); private procedure WMSettingChange(var Message: TWMSettingChange); message WM_SETTINGCHANGE; procedure HandleThemes; end; var Form1: TForm1; implementation {$R *.dfm} uses WindowsDarkMode; procedure TForm1.FormCreate(Sender: TObject); begin HandleThemes; end; procedure TForm1.HandleThemes; begin SetAppropriateThemeMode('Windows10 Dark', 'Windows10'); end; procedure TForm1.WMSettingChange(var Message: TWMSettingChange); begin if SameText('ImmersiveColorSet', String(Message.Section)) then HandleThemes; end; |
テーマに関する補足
テーマの変更を適切に処理するためには、さらに多くのことが必要です。例えば、テーマの「アクセントカラー」の設定がありますが、アプリはこれを検出して可能な限り使用すべきでしょう。さらにボーダーカラーの設定もあります。もしテーマが変更された場合は、「テーマを認識しない」古いコントロールも管理する必要があるため、VCLテーマが変更されたときに正しい値で再描画されません。全体として、ダークモードとライトモードを検出することは、アプリケーションをWindows 10の標準的な外観に近づけるための最大のポイントとなります。
FireMonkeyでのダークモードの対応は?
クロスプラットフォームでダークモードを検出するのは、もう少し複雑です。iOSではFireMonkeyがすでに対応してくれています。ただAndroid、macOS、Linuxはもっと厄介で、特にLinuxは注意が必要です。このブログ記事で紹介しているコードはWindows専用で、FMXスタイルの読み込みにも対応していますが、FireMonkeyアプリでのメッセージングは一般的には少し異なります。
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition