なにがしたい?
HSPで作成したウィンドウはシステムの設定がダークモードになっていてもダークカラーになりません。
Win32APIでダークカラーに対応させようとするとめちゃくちゃ大変っぽいのでせめてタイトルバーだけでもダークカラーに対応する方法をメモ。
もう何のサイトなんだここは。
完成図
上がダークモード時の非アクティブタイトルバー、下がライトカラー時の非アクティブタイトルバー。
ウィンドウの中身は自分で何とかしないといけないけど、これだけでも結構対応しました感出てる。
コード
#include "advapi32.as"
#uselib "dwmapi"
#func DwmGetWindowAttribute "DwmGetWindowAttribute" int, int, int, int
#func DwmSetWindowAttribute "DwmSetWindowAttribute" int, int, int, int
#module
/**
* レジストリの取得
*/
#defcfunc get_regedit int h, str key, str name
// KEY_READ = 0x20019
RegOpenKeyEx h, key, 0, 0x20019, varptr(hkey)
RegQueryValueEx hkey, name, 0, 0, 0, varptr(sz)
if stat == 0 {
sdim data, sz
RegQueryValueEx hkey, name, 0, 0, varptr(data), varptr(sz)
} else {
data = -1
}
RegCloseKey hkey
return data
/**
* システムがダークカラーかどうかをレジストリから取得
* ダークカラーが有効なら1、無効なら0
* そもそもダークカラー設定が存在しない場合は -1 を返す
*/
#defcfunc get_dark_color_type
dark = 0
key = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"
name = "AppsUseLightTheme"
// HKEY_CURRENT_USER = 0x80000001
ret = get_regedit(0x80000001, key, name)
tmpText = ""
if ret != -1 {
// ライトカラー設定
if peek(ret, 0) == 0 {
dark = 1
} else {
dark = 0
}
} else {
dark = -1
}
return dark
#global
title "ダークモード対応タイトルバー"
// システムの設定が変わったときに呼び出される
oncmd gosub *lWM_WININICHANGE, 0x001A
// 起動時に一回呼び出しておく
gosub *lWM_WININICHANGE
stop
// システムの設定が変更された
*lWM_WININICHANGE
// 他の部分はレジストリの変更検出なので、必要なのは実質ここだけ
dim size
dim opt
DwmGetWindowAttribute hwnd, 0, 0, varptr(size)
if get_dark_color_type() == 1 : opt(0) = 1 : else : opt(0) = 0
// DWMWA_USE_IMMERSIVE_DARK_MODE = 20
DwmSetWindowAttribute hwnd, 20, varptr(opt), varptr(size)
return
レジストリの検出を行っているのでリアルタイムに変更される。
必要な個所よりもレジストリ検出の方が多くて面倒。
ちなみに
一応ボタンもダークモード対応できる。
#uselib "uxtheme"
#func SetWindowTheme "SetWindowTheme" int, wptr, nullptr
pos 10, 10 : button "ダークボタン", *lPush
SetWindowTheme objinfo(stat, 2), "DarkMode_Explorer"
stop
*lPush
end
ただし、オブジェクト一つ一つに設定する必要があったり、ボタン以外のオブジェクトは定義の方法が違ったり、
そもそも挙動がおかしくなったりとで使い勝手は最悪。
正直そこまでして対応する必要ない気がする…。