|
|
2023/9/22(Fri) 06:37:07|NO.100064
こちらのサイトを参考し、HSPのダークモードを対応させたのですが、ライトモードかダークモードかどうかを取得する方法はありますか?
https://super-string37.com/entry/2023/01/04/155404
あと、HSPのウィンドウ全体をダークモードすることはできないのでしょうか。
#uselib "dwmapi.dll"
#func DwmSetWindowAttribute "DwmSetWindowAttribute" sptr,sptr,var,sptr
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
value = 1
DwmSetWindowAttribute hwnd,DWMWA_USE_IMMERSIVE_DARK_MODE,value,4
|
|
2023/9/22(Fri) 17:29:53|NO.100066
あと、メニューバーやコンテキストメニューやボタンをダークモードにすることはできないですかね?
|
|
2023/9/22(Fri) 20:37:17|NO.100067
|
|
2023/9/23(Sat) 16:42:45|NO.100073
ダークモードかどうかの判定は以下のサイトが参考になるかと思います。
https://wp.waiei.net/2022/11/16/darkmode-titlebar/
以下、上記のサイトを参考にオブジェクトのダーク化をやってみました。
(ダークモードかどうかの判定は行っていません)
#include "user32.as"
#uselib "dwmapi.dll"
#func DwmSetWindowAttribute "DwmSetWindowAttribute" sptr,sptr,var,sptr
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#module
#uselib "uxtheme"
#func SetWindowTheme "SetWindowTheme" int, wptr, nullptr
#deffunc obj_dark int obj //オブジェクトをダークモード化する(オブジェクトIDを指定する版)
obj_dark_h objinfo(obj,2)
return
#deffunc obj_dark_h int han //オブジェクトをダークモード化する(オブジェクトのハンドルを指定する版)
SetWindowTheme han,"DarkMode_Explorer"
return
#global
value = 1
DwmSetWindowAttribute hwnd,DWMWA_USE_IMMERSIVE_DARK_MODE,value,4
SetWindowPos hwnd,0,0,0,0,0,7 //ダークモードへの変更を反映させる
//以下、オブジェクトをダークモード化
button gosub "テスト",*hoge
obj_dark stat
s="" : mesbox s,400,300
obj_dark stat
stop
*hoge
return
|
|
2023/9/23(Sat) 20:18:08|NO.100074
沢渡さんありがとうございます。そのサイトを参考にして、ダークモードを対応させたところでした。
ダークモードのWindows APIについていろいろ調べてみたら、このサイトによると、SetWindowTheme関数で指定するのは、DarkMode_Explorerだけでなくコンボボックスもダークモード化する場合、
DarkMode_CFDも指定するらしいですが、メニューバーや右クリックメニューやmesboxやinputの入力ボックスの場合、どのようにすればいいのでしょうか?
https://www.haijin-boys.com/wiki/%E3%83%80%E3%83%BC%E3%82%AF%E3%83%A2%E3%83%BC%E3%83%89%E5%AF%BE%E5%BF%9C
//SetWindowTheme関数がUnicodeを使用しているため、hsp3utf.asをインクルードしておく
#include "hsp3utf.as"
#uselib "dwmapi.dll"
#func DwmGetWindowAttribute "DwmGetWindowAttribute" int, int, int, int
#func DwmSetWindowAttribute "DwmSetWindowAttribute" int, int, int, int
#uselib "uxtheme.dll"
#func SetWindowTheme "SetWindowTheme" int, wptr,int
#define dark_obj(%1) SetWindowTheme %1,"DarkMode_Explorer",0
#define dark_com_obj(%1) SetWindowTheme %1,"DarkMode_CFD",0
#define dark_list_obj(%1) SetWindowTheme %1,"DarkMode_ItemsView",0
#define right_obj(%1) SetWindowTheme %1,"",0
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#define WM_WININICHANGE 0x001A
#module
#uselib "advapi32.dll"
#func RegOpenKeyEx "RegOpenKeyExW" int, wptr, int, int,var
#func RegQueryValueEx "RegQueryValueExW" int, wptr, int,int,int,int
#func RegCloseKey "RegCloseKey" int
#define KEY_READ 0x20019
#define HKEY_CURRENT_USER 0x80000001
/**
* レジストリの取得
*/
#defcfunc get_regedit int h, str key, str name
RegOpenKeyEx h, key, 0,KEY_READ,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"
ret = get_regedit(HKEY_CURRENT_USER, key, name)
tmpText = ""
if ret != -1 {
// ライトカラー設定
if peek(ret, 0) == 0 {
dark = 1
} else {
dark = 0
}
} else {
dark = -1
}
return dark
#global
font "meiryo",16
objmode 2
cmb_dummy=0
objsize 120,32
combox cmb_dummy,120,"ダーク\nモード\nテスト"
cmx = objinfo_hwnd(stat)
objsize 120,24
pos 0,33
button "ダーク",*dummy
btn = objinfo_hwnd(stat)
// システムの設定が変わったときに呼び出される
oncmd gosub *lWM_WININICHANGE,WM_WININICHANGE
// 起動時に一回呼び出しておく
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
//タイトルバーをダークモードに変更
DwmSetWindowAttribute hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, varptr(opt), varptr(size)
if opt {
//オブジェクトをダークモードに変更
color 0,0,0:boxf
dark_com_obj cmx
dark_obj btn
}else{
//オブジェクトをライトモードに変更
color 255,255,255:boxf
right_obj cmx
right_obj btn
}
return
*dummy
| |
|
2023/9/24(Sun) 00:02:23|NO.100075
inputやmesboxについては、こんな感じでWM_CTLCOLOREDITを捕まえて
自前で色変更を行う形にするしかないのかな、と思いました。
メニューについてはすみません、ちょっとまだわかりかねます。
//SetWindowTheme関数がUnicodeを使用しているため、hsp3utf.asをインクルードしておく
#include "hsp3utf.as"
#include "gdi32.as"
#include "user32.as"
#uselib "dwmapi.dll"
#func DwmGetWindowAttribute "DwmGetWindowAttribute" int, int, int, int
#func DwmSetWindowAttribute "DwmSetWindowAttribute" int, int, int, int
#uselib "uxtheme.dll"
#func SetWindowTheme "SetWindowTheme" int, wptr,int
#define dark_obj(%1) SetWindowTheme %1,"DarkMode_Explorer",0
#define dark_com_obj(%1) SetWindowTheme %1,"DarkMode_CFD",0
#define dark_list_obj(%1) SetWindowTheme %1,"DarkMode_ItemsView",0
#define right_obj(%1) SetWindowTheme %1,"",0
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#define WM_WININICHANGE 0x001A
#define WM_CTLCOLOREDIT 0x0133
#define RDW_UPDATENOW 1
#module
#uselib "advapi32.dll"
#func RegOpenKeyEx "RegOpenKeyExW" int, wptr, int, int,var
#func RegQueryValueEx "RegQueryValueExW" int, wptr, int,int,int,int
#func RegCloseKey "RegCloseKey" int
#define KEY_READ 0x20019
#define HKEY_CURRENT_USER 0x80000001
/**
* レジストリの取得
*/
#defcfunc get_regedit int h, str key, str name
RegOpenKeyEx h, key, 0,KEY_READ,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"
ret = get_regedit(HKEY_CURRENT_USER, key, name)
tmpText = ""
if ret != -1 {
// ライトカラー設定
if peek(ret, 0) == 0 {
dark = 1
} else {
dark = 0
}
} else {
dark = -1
}
return dark
#global
font "meiryo",16
objmode 2
cmb_dummy=0
objsize 120,32
combox cmb_dummy,120,"ダーク\nモード\nテスト"
cmx = objinfo_hwnd(stat)
objsize 120,24
pos 0,33
button "ダーク",*dummy
btn = objinfo_hwnd(stat)
CreateSolidBrush 0x202020 : br_h=stat //テキストボックスの背景色のブラシ
CreateSolidBrush 0xFFFFFF : br_h2=stat //テキストボックスの背景色のブラシ
input a
inp = objinfo_hwnd(stat)
s=""
mesbox s,400,100
mbox = objinfo_hwnd(stat)
// システムの設定が変わったときに呼び出される
oncmd gosub *lWM_WININICHANGE,WM_WININICHANGE
// 起動時に一回呼び出しておく
gosub *lWM_WININICHANGE
onexit *exit
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
//タイトルバーをダークモードに変更
DwmSetWindowAttribute hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, varptr(opt), varptr(size)
if opt {
//オブジェクトをダークモードに変更
color 0,0,0:boxf
dark_com_obj cmx
dark_obj btn
oncmd gosub *edit_d,WM_CTLCOLOREDIT
}else{
//オブジェクトをライトモードに変更
color 255,255,255:boxf
right_obj cmx
right_obj btn
oncmd gosub *edit_l,WM_CTLCOLOREDIT
}
RedrawWindow inp,0,0,RDW_UPDATENOW //強制再描画
RedrawWindow mbox,0,0,RDW_UPDATENOW
return
*dummy
stop
//ダークモード時のエディットボックス描画
*edit_d
if lparam=inp | lparam=mbox { //lparamがエディットボックスのハンドルかどうかを調べ、そうならば処理を行う。
SetTextColor wparam,0xFFFFFF //文字の色
SetBkColor wparam,0x202020 //背景色
return br_h //ブラシを返す必要がある
}
return
//ライトモード時のエディットボックス描画
*edit_l
if lparam=inp | lparam=mbox {
SetTextColor wparam,0x000000 //文字の色
SetBkColor wparam,0xFFFFFF //背景色
return br_h2 //ブラシを返す必要がある
}
return
*exit
DeleteObject br_h //終了時にブラシを削除
DeleteObject br_h2
end
| |
|
2023/9/24(Sun) 13:04:39|NO.100076
沢渡さんありがとうございます。GUIアプリを作るのに参考になりそうです。
あとinputやmesboxの入力オブジェクトのダークモード化は、Windows 7以前でも動作するのでしょうか?
Windows 10の古いバージョンやWindows 8でDWMWA_USE_IMMERSIVE_DARK_MODEを指定した場合は、エラーが出るのでしょうか?
よろしくお願いします。
あとrightとlightのスペルをミスっていました。
誤 right 正 light
//SetWindowTheme関数がUnicodeを使用しているため、hsp3utf.asをインクルードしておく
#include "hsp3utf.as"
#include "gdi32.as"
#include "user32.as"
#uselib "dwmapi.dll"
#func DwmGetWindowAttribute "DwmGetWindowAttribute" int, int, int, int
#func DwmSetWindowAttribute "DwmSetWindowAttribute" int, int, int, int
#uselib "uxtheme.dll"
#func SetWindowTheme "SetWindowTheme" int, wptr,int
#define dark_obj(%1) SetWindowTheme %1,"DarkMode_Explorer",0
#define dark_com_obj(%1) SetWindowTheme %1,"DarkMode_CFD",0
#define dark_list_obj(%1) SetWindowTheme %1,"DarkMode_ItemsView",0
#define light_obj(%1) SetWindowTheme %1,"",0
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#define WM_WININICHANGE 0x001A
#define WM_CTLCOLOREDIT 0x0133
#define RDW_UPDATENOW 1
#module
#uselib "advapi32.dll"
#func RegOpenKeyEx "RegOpenKeyExW" int, wptr, int, int,var
#func RegQueryValueEx "RegQueryValueExW" int, wptr, int,int,int,int
#func RegCloseKey "RegCloseKey" int
#define KEY_READ 0x20019
#define HKEY_CURRENT_USER 0x80000001
/**
* レジストリの取得
*/
#defcfunc get_regedit int h, str key, str name
RegOpenKeyEx h, key, 0,KEY_READ,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"
ret = get_regedit(HKEY_CURRENT_USER, key, name)
tmpText = ""
if ret != -1 {
// ライトカラー設定
if peek(ret, 0) == 0 {
dark = 1
} else {
dark = 0
}
} else {
dark = -1
}
return dark
#global
font "meiryo",16
objmode 2
cmb_dummy=0
objsize 120,32
combox cmb_dummy,120,"ダーク\nモード\nテスト"
cmx = objinfo_hwnd(stat)
objsize 120,24
pos 0,33
button "ダーク",*dummy
btn = objinfo_hwnd(stat)
CreateSolidBrush 0x202020 : br_h=stat //テキストボックスの背景色のブラシ
CreateSolidBrush 0xFFFFFF : br_h2=stat //テキストボックスの背景色のブラシ
input a
inp = objinfo_hwnd(stat)
s=""
mesbox s,400,100
mbox = objinfo_hwnd(stat)
// システムの設定が変わったときに呼び出される
oncmd gosub *lWM_WININICHANGE,WM_WININICHANGE
// 起動時に一回呼び出しておく
gosub *lWM_WININICHANGE
onexit *exit
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
//タイトルバーをダークモードに変更
DwmSetWindowAttribute hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, varptr(opt), varptr(size)
if opt {
//オブジェクトをダークモードに変更
color 0,0,0:boxf
dark_com_obj cmx
dark_obj mbox//スクロールバーをダークモード化
dark_obj btn
oncmd gosub *edit_d,WM_CTLCOLOREDIT
}else{
//オブジェクトをライトモードに変更
color 255,255,255:boxf
light_obj cmx
light_obj mbox
light_obj btn
oncmd gosub *edit_l,WM_CTLCOLOREDIT
}
RedrawWindow inp,0,0,RDW_UPDATENOW //強制再描画
RedrawWindow mbox,0,0,RDW_UPDATENOW
return
*dummy
stop
//ダークモード時のエディットボックス描画
*edit_d
if lparam=inp | lparam=mbox { //lparamがエディットボックスのハンドルかどうかを調べ、そうならば処理を行う。
SetTextColor wparam,0xFFFFFF //文字の色
SetBkColor wparam,0x202020 //背景色
return br_h //ブラシを返す必要がある
}
return
//ライトモード時のエディットボックス描画
*edit_l
if lparam=inp | lparam=mbox {
SetTextColor wparam,0x000000 //文字の色
SetBkColor wparam,0xFFFFFF //背景色
return br_h2 //ブラシを返す必要がある
}
return
*exit
DeleteObject br_h //終了時にブラシを削除
DeleteObject br_h2
end
| |
|
2023/9/24(Sun) 16:18:46|NO.100077
追記です。
ポップアップメニューについてはSetPreferredAppModeと
RefreshImmersiveColorPolicyStateを使えばできたのですが、
ウィンドウの上に貼り付くメニューについてはそれも効きませんでした。
色々調べてみてもよくわからなかったので、通常のメニューの代わりに
「ボタンを配置し、それ以外の部分はスタティックコントロールで穴埋め」
したもので代用してみましたが、このような形でどうでしょうか?
(本当はボタンの境界線も消したかったのですが、Windows10以降では
ウィンドウスタイルにBS_FLATを指定してもダメな様子……?)
//SetWindowTheme関数がUnicodeを使用しているため、hsp3utf.asをインクルードしておく
#include "hsp3utf.as"
#include "gdi32.as"
#include "user32.as"
#include "kernel32.as"
#uselib "dwmapi.dll"
#func DwmGetWindowAttribute "DwmGetWindowAttribute" int, int, int, int
#func DwmSetWindowAttribute "DwmSetWindowAttribute" int, int, int, int
#uselib "uxtheme.dll"
#func SetWindowTheme "SetWindowTheme" int, wptr,int
#define dark_obj(%1) SetWindowTheme %1,"DarkMode_Explorer",0
#define dark_com_obj(%1) SetWindowTheme %1,"DarkMode_CFD",0
#define dark_list_obj(%1) SetWindowTheme %1,"DarkMode_ItemsView",0
#define right_obj(%1) SetWindowTheme %1,"",0
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#define WM_WININICHANGE 0x001A
#define WM_CTLCOLOREDIT 0x0133
#define WM_CTLCOLORSTATIC 0x0138
#define RDW_UPDATENOW 1
#module
#uselib "advapi32.dll"
#func RegOpenKeyEx "RegOpenKeyExW" int, wptr, int, int,var
#func RegQueryValueEx "RegQueryValueExW" int, wptr, int,int,int,int
#func RegCloseKey "RegCloseKey" int
#define KEY_READ 0x20019
#define HKEY_CURRENT_USER 0x80000001
/**
* レジストリの取得
*/
#defcfunc get_regedit int h, str key, str name
RegOpenKeyEx h, key, 0,KEY_READ,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"
ret = get_regedit(HKEY_CURRENT_USER, key, name)
tmpText = ""
if ret != -1 {
// ライトカラー設定
if peek(ret, 0) == 0 {
dark = 1
} else {
dark = 0
}
} else {
dark = -1
}
return dark
#global
font "meiryo",16
objmode 2
cmb_dummy=0
pos 0,30
objsize 120,32
combox cmb_dummy,120,"ダーク\nモード\nテスト"
cmx = objinfo_hwnd(stat)
objsize 120,24
pos 0,63
button "ダーク",*dummy
btn = objinfo_hwnd(stat)
CreateSolidBrush 0x202020 : br_h=stat //テキストボックスの背景色のブラシ
CreateSolidBrush 0xFFFFFF : br_h2=stat
CreateSolidBrush 0xE1E1E1 : br_h3=stat //スタティックコントロールの背景色のブラシ
input a
inp = objinfo_hwnd(stat)
s=""
mesbox s,400,100
mbox = objinfo_hwnd(stat)
//メニュー代わりのボタン
pos 0,0
objsize 160,30
button gosub "ポップアップ",*popup
menubtn1=objinfo_hwnd(stat)
GetWindowLong menubtn1,-16
SetWindowLong menubtn1,-16,stat|0x8100
//穴埋め用のスタティックコントロール
objsize 480,30 : pos 160,0
winobj "static","",,0x50000000
static=objinfo_hwnd(stat)
//ポップアップメニュー関連
CreatePopupMenu : pmenu=stat
AppendMenuW pmenu,0,0,"ポップアップしました"
LoadLibraryW "uxtheme.dll" : lib_h=stat //SetPreferredAppModeとRefreshImmersiveColorPolicyStateを呼ぶための準備
//これらのAPIは非公開のためか、一寸迂遠な方法で呼ぶしかなさそう?
// システムの設定が変わったときに呼び出される
oncmd gosub *lWM_WININICHANGE,WM_WININICHANGE
// 起動時に一回呼び出しておく
gosub *lWM_WININICHANGE
onexit *exit
stop
// システムの設定が変更された
*lWM_WININICHANGE
// 他の部分はレジストリの変更検出なので、必要なのは実質ここだけ
dim size
dim opt
dim prm,2
GetProcAddress lib_h,135 : add=stat //SetPreferredAppModeのアドレスを取得
prm=2 : dum=callfunc(prm,add,1) //SetPreferredAppModeを実行
//ウィンドウの属性状態を取得
//DwmGetWindowAttribute hwnd, 0, 0, 4
if get_dark_color_type() == 1 : opt(0) = 1 : else : opt(0) = 0
//タイトルバーをダークモードに変更
DwmSetWindowAttribute hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, varptr(opt), 4
if opt {
//オブジェクトをダークモードに変更
color 0,0,0:boxf
dark_com_obj cmx
dark_obj btn
dark_obj menubtn1
oncmd gosub *edit_d,WM_CTLCOLOREDIT
oncmd gosub *edit_d,WM_CTLCOLORSTATIC
}else{
//オブジェクトをライトモードに変更
GetProcAddress lib_h,135 : add=stat //SetPreferredAppModeのアドレスを取得
prm=3 : dum=callfunc(prm,add,1) //SetPreferredAppModeを実行
color 255,255,255:boxf
right_obj cmx
right_obj btn
right_obj menubtn1
oncmd gosub *edit_l,WM_CTLCOLOREDIT
oncmd gosub *edit_l,WM_CTLCOLORSTATIC
}
GetProcAddress lib_h,104 : add=stat //RefreshImmersiveColorPolicyStateのアドレスを取得
dum=callfunc(prm,add,0) //RefreshImmersiveColorPolicyStateを実行
RedrawWindow inp,0,0,RDW_UPDATENOW //強制再描画
RedrawWindow mbox,0,0,RDW_UPDATENOW
RedrawWindow static,0,0,RDW_UPDATENOW
return
*dummy
stop
//ダークモード時のエディットボックス描画
*edit_d
if lparam=inp | lparam=mbox | lparam=static { //lparamがエディットボックスのハンドルかどうかを調べ、そうならば処理を行う。
SetTextColor wparam,0xFFFFFF //文字の色
SetBkColor wparam,0x202020 //背景色
return br_h //ブラシを返す必要がある
}
return
//ライトモード時のエディットボックス描画
*edit_l
if lparam=inp | lparam=mbox | lparam=static {
SetTextColor wparam,0x000000 //文字の色
if lparam=static {
SetBkColor wparam,0xE1E1E1 //背景色
return br_h3
} else {
SetBkColor wparam,0xFFFFFF //背景色
return br_h2
}
}
return
*popup
TrackPopupMenu pmenu,0,ginfo_mx,ginfo_my,0,hwnd,0
return
*exit
DeleteObject br_h //終了時にブラシを削除
DeleteObject br_h2
DeleteObject br_h3
DestroyMenu pmenu //メニューを削除
FreeLibrary lib_h //読み込んだライブラリを解放
end
>あとinputやmesboxの入力オブジェクトのダークモード化は、
>Windows 7以前でも動作するのでしょうか?
WM_WININICHANGEやSetTextColor等はWindows2000以降で使えるようなので、
おそらく大丈夫だと思います。
>Windows 10の古いバージョンやWindows 8でDWMWA_USE_IMMERSIVE_DARK_MODEを
>指定した場合は、エラーが出るのでしょうか?
試せる環境がないので断言はできませんが、
DwmSetWindowAttribute自体はWindowsVistaからサポートされているようなので、
HSPがエラーで落ちるようなことは無いとは思います。
| |
|
2023/9/24(Sun) 23:45:49|NO.100082
おお、そんな方法でダークモードにできたんですね。
uselibのfuncからuxtheme.dllのSetPreferredAppModeを呼び出そうとしても、dllの呼び出しエラーが出たのでできないと思っていたのですが。
//SetWindowTheme関数がUnicodeを使用しているため、hsp3utf.asをインクルードしておく
#include "hsp3utf.as"
#uselib "gdi32.dll"
#cfunc CreateSolidBrush "CreateSolidBrush" int
#func DeleteObject "DeleteObject" int
#func SetTextColor "SetTextColor" int,int
#func SetBkColor "SetBkColor" int,int
#uselib "user32.dll"
#func GetWindowLong "GetWindowLongW" int,int
#func SetWindowLong "SetWindowLongW" int,int,int
#cfunc CreatePopupMenu "CreatePopupMenu"
#func AppendMenu "AppendMenuW" int,int,int,wstr
#func RedrawWindow "RedrawWindow" int,int,int,int
#func TrackPopupMenu "TrackPopupMenu" int, int, int, int, int, int, int
#func DestroyMenu "DestroyMenu" int
#uselib "kernel32.dll"
#cfunc LoadLibrary "LoadLibraryW" wstr
#cfunc GetProcAddress "GetProcAddress" int,int
#func FreeLibrary "FreeLibrary" int
#uselib "dwmapi.dll"
#func DwmGetWindowAttribute "DwmGetWindowAttribute" int, int, int, int
#func DwmSetWindowAttribute "DwmSetWindowAttribute" int, int, int, int
#uselib "uxtheme.dll"
#func SetWindowTheme "SetWindowTheme" int, wptr,wptr
#define dark_obj(%1) SetWindowTheme %1,"DarkMode_Explorer",0
#define dark_com_obj(%1) SetWindowTheme %1,"DarkMode_CFD",0
#define dark_list_obj(%1) SetWindowTheme %1,"DarkMode_ItemsView",0
#define light_obj(%1) SetWindowTheme %1,"",0
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#define WM_WININICHANGE 0x001A
#define WM_CTLCOLOREDIT 0x0133
#define WM_CTLCOLORSTATIC 0x0138
#define RDW_UPDATENOW 1
#module
#uselib "advapi32.dll"
#func RegOpenKeyEx "RegOpenKeyExW" int, wptr, int, int,var
#func RegQueryValueEx "RegQueryValueExW" int, wptr, int,int,int,int
#func RegCloseKey "RegCloseKey" int
#define KEY_READ 0x20019
#define HKEY_CURRENT_USER 0x80000001
/**
* レジストリの取得
*/
#defcfunc get_regedit int h, str key, str name
RegOpenKeyEx h, key, 0,KEY_READ,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"
ret = get_regedit(HKEY_CURRENT_USER, key, name)
tmpText = ""
if ret != -1 {
// ライトカラー設定
if peek(ret, 0) == 0 {
dark = 1
} else {
dark = 0
}
} else {
dark = -1
}
return dark
#global
font "meiryo",16
objmode 2
cmb_dummy=0
pos 0,30
objsize 120,32
combox cmb_dummy,120,"ダーク\nモード\nテスト"
cmx = objinfo_hwnd(stat)
objsize 120,32
pos 120,30
button "ダーク",*dummy
btn = objinfo_hwnd(stat)
br_h = CreateSolidBrush(0x202020) //テキストボックスの背景色のブラシ
br_h2 = CreateSolidBrush(0xFFFFFF)
br_h3 = CreateSolidBrush(0xE1E1E1)//スタティックコントロールの背景色のブラシ
pos 0
a = "ダークモードテスト"
input a,ginfo_winx
inp = objinfo_hwnd(stat)
sdim s
mesbox s,ginfo_winx,ginfo_winy-94
mbox = objinfo_hwnd(stat)
//メニュー代わりのボタン
pos 0,0
objsize 160,30
button gosub "ポップアップ",*popup
menubtn1=objinfo_hwnd(stat)
GetWindowLong menubtn1,-16
SetWindowLong menubtn1,-16,stat|0x8100
//穴埋め用のスタティックコントロール
objsize 480,30 : pos 160,0
winobj "static","",,0x50000000
static=objinfo_hwnd(stat)
//ポップアップメニュー関連
pmenu=CreatePopupMenu()
AppendMenu pmenu,0,0,"ポップアップメニュー"
lib_h = LoadLibrary("uxtheme.dll") //SetPreferredAppModeとRefreshImmersiveColorPolicyStateを呼ぶための準備
//これらのAPIは非公開のためか、一寸迂遠な方法で呼ぶしかなさそう?
// システムの設定が変わったときに呼び出される
oncmd gosub *lWM_WININICHANGE,WM_WININICHANGE
// 起動時に一回呼び出しておく
gosub *lWM_WININICHANGE
onexit *exit
stop
// システムの設定が変更された
*lWM_WININICHANGE
// 他の部分はレジストリの変更検出なので、必要なのは実質ここだけ
dim size
dim opt
dim prm,2
//ウィンドウの属性状態を取得
//DwmGetWindowAttribute hwnd, 0, 0, 4
if get_dark_color_type() == 1 : opt(0) = 1 : else : opt(0) = 0
//タイトルバーをダークモードに変更
DwmSetWindowAttribute hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, varptr(opt), 4
add = GetProcAddress(lib_h,135) //SetPreferredAppModeのアドレスを取得
prm=2 : dum=callfunc(prm,add,1) //SetPreferredAppModeを実行
if opt {
//オブジェクトをダークモードに変更
color 0,0,0:boxf
dark_com_obj cmx
dark_obj btn
dark_obj menubtn1
dark_obj mbox
oncmd gosub *edit_d,WM_CTLCOLOREDIT
oncmd gosub *edit_d,WM_CTLCOLORSTATIC
}else{
//オブジェクトをライトモードに変更
add = GetProcAddress(lib_h,135) //SetPreferredAppModeのアドレスを取得
prm=3 : dum=callfunc(prm,add,1) //SetPreferredAppModeを実行
color 255,255,255:boxf
light_obj cmx
light_obj btn
light_obj menubtn1
light_obj mbox
oncmd gosub *edit_l,WM_CTLCOLOREDIT
oncmd gosub *edit_l,WM_CTLCOLORSTATIC
}
add=GetProcAddress(lib_h,104) //RefreshImmersiveColorPolicyStateのアドレスを取得
dum=callfunc(prm,add,0) //RefreshImmersiveColorPolicyStateを実行
RedrawWindow inp,0,0,RDW_UPDATENOW //強制再描画
RedrawWindow mbox,0,0,RDW_UPDATENOW
RedrawWindow static,0,0,RDW_UPDATENOW
return
*dummy
stop
//ダークモード時のエディットボックス描画
*edit_d
if lparam=inp | lparam=mbox | lparam=static { //lparamがエディットボックスのハンドルかどうかを調べ、そうならば処理を行う。
SetTextColor wparam,0xFFFFFF //文字の色
SetBkColor wparam,0x202020 //背景色
return br_h //ブラシを返す必要がある
}
return
//ライトモード時のエディットボックス描画
*edit_l
if lparam=inp | lparam=mbox | lparam=static {
SetTextColor wparam,0x000000 //文字の色
if lparam=static {
SetBkColor wparam,0xE1E1E1 //背景色
return br_h3
} else {
SetBkColor wparam,0xFFFFFF //背景色
return br_h2
}
}
return
*popup
TrackPopupMenu pmenu,0,ginfo_mx,ginfo_my,0,hwnd,0
return
*exit
DeleteObject br_h //終了時にブラシを削除
DeleteObject br_h2
DeleteObject br_h3
DestroyMenu pmenu //メニューを削除
FreeLibrary lib_h //読み込んだライブラリを解放
end
少しスクリプトを改造してみましたが、実行中にWindowsの設定からライトモードに切り替えた際に、ポップアップメニューだけライトモードにならないのですが、これは仕様なのでしょうか?
| |
|
2023/9/25(Mon) 00:56:33|NO.100083
横からですが、ご報告という事で。
Windows10 Home 22H2にて、
設定をライト→ダークに変更時、ダーク→ライトに変更時どちらとも、
ポップアップメニューも含め設定どおりに変更されている為、
環境的な問題だと思います。
|
|
2023/9/26(Tue) 17:19:20|NO.100085
>No.100067
がちですみませんでした、つぎからはしっかりとおしえたいとおもいます
|
|
2023/9/28(Thu) 06:57:09|NO.100095
右クリックメニューがなぜか変わらないです。
一応ポップアップメニューが反映されたということで解決チェック入れておきます。
|
|
2023/9/28(Thu) 10:49:44|NO.100096
すみません、もしかしたらこれで上手くいくかもしれません。
ライト/ダークの切り替えのたびにSetPreferredAppModeを呼ぶのではなく、
SetPreferredAppModeのオプションを1(APPMODE_ALLOWDARK)にして
最初に1回だけ呼ぶようにするだけで、当方の環境(Windows10)では
ライト/ダークの切り替えがポップアップメニューに反映されました。
訳あって現在Windows11が使えないので、Windows11ではどうなるかわかりません。
これで上手くいけばいいのですが。
//SetWindowTheme関数がUnicodeを使用しているため、hsp3utf.asをインクルードしておく
#include "hsp3utf.as"
#uselib "gdi32.dll"
#cfunc CreateSolidBrush "CreateSolidBrush" int
#func DeleteObject "DeleteObject" int
#func SetTextColor "SetTextColor" int,int
#func SetBkColor "SetBkColor" int,int
#uselib "user32.dll"
#func GetWindowLong "GetWindowLongW" int,int
#func SetWindowLong "SetWindowLongW" int,int,int
#cfunc CreatePopupMenu "CreatePopupMenu"
#func AppendMenu "AppendMenuW" int,int,int,wstr
#func RedrawWindow "RedrawWindow" int,int,int,int
#func TrackPopupMenu "TrackPopupMenu" int, int, int, int, int, int, int
#func DestroyMenu "DestroyMenu" int
#uselib "kernel32.dll"
#cfunc LoadLibrary "LoadLibraryW" wstr
#cfunc GetProcAddress "GetProcAddress" int,int
#func FreeLibrary "FreeLibrary" int
#uselib "dwmapi.dll"
#func DwmGetWindowAttribute "DwmGetWindowAttribute" int, int, int, int
#func DwmSetWindowAttribute "DwmSetWindowAttribute" int, int, int, int
#uselib "uxtheme.dll"
#func SetWindowTheme "SetWindowTheme" int, wptr,wptr
#define dark_obj(%1) SetWindowTheme %1,"DarkMode_Explorer",0
#define dark_com_obj(%1) SetWindowTheme %1,"DarkMode_CFD",0
#define dark_list_obj(%1) SetWindowTheme %1,"DarkMode_ItemsView",0
#define light_obj(%1) SetWindowTheme %1,"",0
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
#define WM_WININICHANGE 0x001A
#define WM_CTLCOLOREDIT 0x0133
#define WM_CTLCOLORSTATIC 0x0138
#define RDW_UPDATENOW 1
#module
#uselib "advapi32.dll"
#func RegOpenKeyEx "RegOpenKeyExW" int, wptr, int, int,var
#func RegQueryValueEx "RegQueryValueExW" int, wptr, int,int,int,int
#func RegCloseKey "RegCloseKey" int
#define KEY_READ 0x20019
#define HKEY_CURRENT_USER 0x80000001
/**
* レジストリの取得
*/
#defcfunc get_regedit int h, str key, str name
RegOpenKeyEx h, key, 0,KEY_READ,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"
ret = get_regedit(HKEY_CURRENT_USER, key, name)
tmpText = ""
if ret != -1 {
// ライトカラー設定
if peek(ret, 0) == 0 {
dark = 1
} else {
dark = 0
}
} else {
dark = -1
}
return dark
#global
font "meiryo",16
objmode 2
cmb_dummy=0
pos 0,30
objsize 120,32
combox cmb_dummy,120,"ダーク\nモード\nテスト"
cmx = objinfo_hwnd(stat)
objsize 120,32
pos 120,30
button "ダーク",*dummy
btn = objinfo_hwnd(stat)
br_h = CreateSolidBrush(0x202020) //テキストボックスの背景色のブラシ
br_h2 = CreateSolidBrush(0xFFFFFF)
br_h3 = CreateSolidBrush(0xE1E1E1)//スタティックコントロールの背景色のブラシ
pos 0
a = "ダークモードテスト"
input a,ginfo_winx
inp = objinfo_hwnd(stat)
sdim s
mesbox s,ginfo_winx,ginfo_winy-94
mbox = objinfo_hwnd(stat)
//メニュー代わりのボタン
pos 0,0
objsize 160,30
button gosub "ポップアップ",*popup
menubtn1=objinfo_hwnd(stat)
GetWindowLong menubtn1,-16
SetWindowLong menubtn1,-16,stat|0x8100
//穴埋め用のスタティックコントロール
objsize 480,30 : pos 160,0
winobj "static","",,0x50000000
static=objinfo_hwnd(stat)
//ポップアップメニュー関連
pmenu=CreatePopupMenu()
AppendMenu pmenu,0,0,"ポップアップメニュー"
//これらのAPIは非公開のためか、一寸迂遠な方法で呼ぶしかなさそう?
lib_h = LoadLibrary("uxtheme.dll") //SetPreferredAppModeとRefreshImmersiveColorPolicyStateを呼ぶための準備
add = GetProcAddress(lib_h,135) //SetPreferredAppModeのアドレスを取得
prm=1 : dum=callfunc(prm,add,1) //SetPreferredAppModeを実行
add=GetProcAddress(lib_h,104) //RefreshImmersiveColorPolicyStateのアドレスを取得
dum=callfunc(prm,add,0) //RefreshImmersiveColorPolicyStateを実行
// システムの設定が変わったときに呼び出される
oncmd gosub *lWM_WININICHANGE,WM_WININICHANGE
// 起動時に一回呼び出しておく
gosub *lWM_WININICHANGE
onexit *exit
stop
// システムの設定が変更された
*lWM_WININICHANGE
// 他の部分はレジストリの変更検出なので、必要なのは実質ここだけ
dim size
dim opt
dim prm,2
//ウィンドウの属性状態を取得
//DwmGetWindowAttribute hwnd, 0, 0, 4
if get_dark_color_type() == 1 : opt = 1 : else : opt = 0
//タイトルバーをダークモードに変更
DwmSetWindowAttribute hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, varptr(opt), 4
if opt {
//オブジェクトをダークモードに変更
color 0,0,0:boxf
dark_com_obj cmx
dark_obj btn
dark_obj menubtn1
dark_obj mbox
oncmd gosub *edit_d,WM_CTLCOLOREDIT
oncmd gosub *edit_d,WM_CTLCOLORSTATIC
}else{
color 255,255,255:boxf
light_obj cmx
light_obj btn
light_obj menubtn1
light_obj mbox
oncmd gosub *edit_l,WM_CTLCOLOREDIT
oncmd gosub *edit_l,WM_CTLCOLORSTATIC
}
RedrawWindow inp,0,0,RDW_UPDATENOW //強制再描画
RedrawWindow mbox,0,0,RDW_UPDATENOW
RedrawWindow static,0,0,RDW_UPDATENOW
return
*dummy
stop
//ダークモード時のエディットボックス描画
*edit_d
if lparam=inp | lparam=mbox | lparam=static { //lparamがエディットボックスのハンドルかどうかを調べ、そうならば処理を行う。
SetTextColor wparam,0xFFFFFF //文字の色
SetBkColor wparam,0x202020 //背景色
return br_h //ブラシを返す必要がある
}
return
//ライトモード時のエディットボックス描画
*edit_l
if lparam=inp | lparam=mbox | lparam=static {
SetTextColor wparam,0x000000 //文字の色
if lparam=static {
SetBkColor wparam,0xE1E1E1 //背景色
return br_h3
} else {
SetBkColor wparam,0xFFFFFF //背景色
return br_h2
}
}
return
*popup
TrackPopupMenu pmenu,0,ginfo_mx,ginfo_my,0,hwnd,0
return
*exit
DeleteObject br_h //終了時にブラシを削除
DeleteObject br_h2
DeleteObject br_h3
DestroyMenu pmenu //メニューを削除
FreeLibrary lib_h //読み込んだライブラリを解放
end
| |
|
2023/9/28(Thu) 14:18:03|NO.100097
あれ、右クリックメニューも含めてしっかり切り替わってたんですが、
沢渡さんの書き方を見る感じそちらも反映されてなかったっぽいので
何方かというとこちらの環境が特殊な感じだったのかな?
>>100096のコードも確認しましたがこちらではしっかり切り替わってました。
|
|
2023/9/28(Thu) 15:24:46|NO.100098
すみません、言い足りませんでした。
NO.100077、NO.100082、NO.100096、いずれのコードも当方のWindows10環境では
想定通りの動作になりますが、ゆっくりXPさんの環境ではNO.100096のようにすれば
上手く行くかなと思っての投稿でした。
|
|
2023/9/28(Thu) 19:08:46|NO.100102
>>100098
なるほど、理解しました。
Windows10と11で仕様が微妙に変わったとか、この辺の違いなのかもですね。
横からのお目汚し失礼しました。
|
|
2023/9/29(Fri) 10:48:31|NO.100104
追記です。Windows11での動作確認ができるようになったので確認しました。
私が先に挙げたNO.100077のコードですと、確かに
「実行中にWindowsの設定からライトモードに切り替えた際に、
ポップアップメニューだけライトモードにならない」
という現象が発生しましたが、NO.100096の場合だと上手く行くようです。
|
|
2023/9/29(Fri) 23:07:15|NO.100105
おお、Windows11でもわざわざ検証ありがとうございます!
自分の環境はWindows 11ですが、コンテストメニューも問題なく反映されたようです。
メニューバーは結構難しそうな感じですかね…?
とりあえず解決済みです。
|
|