api - tablacus/TablacusDark GitHub Wiki

ダークモード関連の非公開API

非公開APIは名前が無い場合が多いのでその時は数値でGetProcAddressします。

ShouldAppsUseDarkMode @uxtheme.dll,132

アプリがダークモードが有効か調べる。

※ハイコントラストの場合はダークモード関係ないのでハイコントラストのテーマかも調べましょう。

AllowDarkModeForWindow @uxtheme.dll,133

ウインドウやコントロールにダークモードを設定する。 TRUEをセットすると

SetWindowTheme(hwnd, L"explorer", NULL);

SetWindowTheme(hwnd, L"darkmode_explorer", NULL);

と同じ感じになる(SysListView32だけ例外あり)

SetPreferredAppMode @uxtheme.dll,135

そのアプリがダークモードか否かを設定。 とりあえず、これを設定するだけでメニューはダークモードになる。(カスタムドローしている場合は除く)

APPMODE_DEFAULT = 0,
APPMODE_ALLOWDARK = 1,
APPMODE_FORCEDARK = 2,
APPMODE_FORCELIGHT = 3,

今は APPMODE_FORCEDARK や APPMODE_FORCELIGHT を一度使うとずーとダークモード、ライトモードになり、ライトモード/ダークモードの切り替えができなくなる。

だから、ライトモードは APPMODE_DEFAULT 、ダークモードは APPMODE_ALLOWDARK にするのがお勧め。

RefreshImmersiveColorPolicyState @uxtheme.dll,104

ダークモード切替後に呼ぶと良いようだ。

IsDarkModeAllowedForWindow @uxtheme.dll,137

ウインドウがダークモードかどうか調べる。SetPreferredAppMode もダークモードになってないと取得できなかった。

SetWindowCompositionAttribute @user32.dll,"SetWindowCompositionAttribute"

DwmSetWindowAttribute @dwmapi.dll,"DwmSetWindowAttribute"

タイトルバーをダークモード化するのに使う。途中で仕様が変わったので SetWindowCompositionAttribute が使えたら SetWindowCompositionAttribute 使えなかったら DwmSetWindowAttribute を使う


#ifndef PreferredAppMode
enum PreferredAppMode
{
	APPMODE_DEFAULT = 0,
	APPMODE_ALLOWDARK = 1,
	APPMODE_FORCEDARK = 2,
	APPMODE_FORCELIGHT = 3,
	APPMODE_MAX = 4
};
#endif
#ifndef WINCOMPATTRDATA
struct WINCOMPATTRDATA
{
	DWORD dwAttrib;
	PVOID pvData;
	SIZE_T cbData;
};
#endif

typedef PreferredAppMode (WINAPI* LPFNSetPreferredAppMode)(PreferredAppMode appMode);
typedef bool (WINAPI* LPFNAllowDarkModeForWindow)(HWND hwnd, BOOL allow);
typedef bool (WINAPI* LPFNShouldAppsUseDarkMode)();
typedef void (WINAPI* LPFNRefreshImmersiveColorPolicyState)();
typedef bool (WINAPI* LPFNIsDarkModeAllowedForWindow)(HWND hwnd);
typedef BOOL(WINAPI* LPFNSetWindowCompositionAttribute)(HWND hWnd, WINCOMPATTRDATA*);
typedef HRESULT (STDAPICALLTYPE * LPFNDwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD   cbAttribute);

LPFNSetPreferredAppMode _SetPreferredAppMode = NULL;
LPFNAllowDarkModeForWindow _AllowDarkModeForWindow = NULL;
LPFNShouldAppsUseDarkMode _ShouldAppsUseDarkMode = NULL;
LPFNRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState = NULL;
LPFNIsDarkModeAllowedForWindow _IsDarkModeAllowedForWindow = NULL;
LPFNSetWindowCompositionAttribute _SetWindowCompositionAttribute = NULL;
LPFNDwmSetWindowAttribute _DwmSetWindowAttribute = NULL;

		if (hDll = LoadLibraryA("uxtheme.dll")) {
			*(FARPROC *)&_ShouldAppsUseDarkMode = GetProcAddress(hDll, MAKEINTRESOURCEA(132));
			*(FARPROC *)&_AllowDarkModeForWindow = GetProcAddress(hDll, MAKEINTRESOURCEA(133));
			*(FARPROC *)&_SetPreferredAppMode = GetProcAddress(hDll, MAKEINTRESOURCEA(135));
			*(FARPROC *)&_RefreshImmersiveColorPolicyState = GetProcAddress(hDll, MAKEINTRESOURCEA(104));
			*(FARPROC *)&_IsDarkModeAllowedForWindow = GetProcAddress(hDll, MAKEINTRESOURCEA(137));
			FreeLibrary(hDll);
		}
		if (hDll = LoadLibraryA("user32.dll")) {
			*(FARPROC *)&_SetWindowCompositionAttribute = GetProcAddress(hDll, "SetWindowCompositionAttribute");
			FreeLibrary(hDll);
		}
		if (!_SetWindowCompositionAttribute) {
			if (hDll = LoadLibraryA("dwmapi.dll")) {
				*(FARPROC *)&_DwmSetWindowAttribute = GetProcAddress(hDll, "DwmSetWindowAttribute");
				FreeLibrary(hDll);
			}
		}