HSP – タイトルバーのダークカラー対応

なにがしたい?

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
ダークモード対応ボタン

ただし、オブジェクト一つ一つに設定する必要があったり、ボタン以外のオブジェクトは定義の方法が違ったり、
そもそも挙動がおかしくなったりとで使い勝手は最悪。
正直そこまでして対応する必要ない気がする…。