In comctl32 DllMain(), IsThemeActive() is a delay-loaded function and shouldn't be called in DllMain(). Instead, tests showed that uxtheme should be loaded by user32.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51540 Signed-off-by: Zhiyi Zhang zzhang@codeweavers.com --- Further tests not included in this patch series show that uxtheme gets unloaded when theming is turned off and gets loaded when theming is turned on even after application startup. This dynamic loading/unloading behavior requires at least a window and a message loop (merely calling GetMessage() is enough), which suggests a WH_GETMESSAGE hook is installed and listens for WM_THEMECHANGED. The WM_THEMECHANGED lparam is a reserved parameter that is TRUE then theming is active and FALSE otherwise. Due to the WH_GETMESSAGE hook involved, I decided not to implement the dynamic loading and unloading of uxtheme for user32 to avoid filtering every messages.
Also a test application that doesn't link to comctl32 and doesn't have a comctl32 v6 manifest still has its standard scrollbars and dialogs themed when theming is active.
dlls/comctl32/commctrl.c | 3 --- dlls/user32/class.c | 16 ++++++++++++++++ dlls/user32/tests/class.c | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c index 1c7718e2400..b457bdcb8be 100644 --- a/dlls/comctl32/commctrl.c +++ b/dlls/comctl32/commctrl.c @@ -208,9 +208,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) TRACKBAR_Register (); TREEVIEW_Register (); UPDOWN_Register (); - - /* Call IsThemeActive() so that delay-loaded uxtheme.dll is loaded for hooking user32 */ - IsThemeActive(); break;
case DLL_PROCESS_DETACH: diff --git a/dlls/user32/class.c b/dlls/user32/class.c index c17a612c5b9..cef52883988 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -539,6 +539,19 @@ static void register_builtin( const struct builtin_class_descr *descr ) release_class_ptr( classPtr ); }
+static void load_uxtheme(void) +{ + BOOL (WINAPI * pIsThemeActive)(void); + HMODULE uxtheme; + + uxtheme = LoadLibraryA("uxtheme.dll"); + if (uxtheme) + { + pIsThemeActive = (void *)GetProcAddress(uxtheme, "IsThemeActive"); + if (!pIsThemeActive || !pIsThemeActive()) + FreeLibrary(uxtheme); + } +}
/*********************************************************************** * register_builtins @@ -557,6 +570,9 @@ static BOOL WINAPI register_builtins( INIT_ONCE *once, void *param, void **conte register_builtin( &SCROLL_builtin_class ); register_builtin( &STATIC_builtin_class ); register_builtin( &IME_builtin_class ); + + /* Load uxtheme.dll so that standard scrollbars and dialogs are hooked for theming support */ + load_uxtheme(); return TRUE; }
diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c index 0f4fd1cf90e..e6762032107 100644 --- a/dlls/user32/tests/class.c +++ b/dlls/user32/tests/class.c @@ -1511,6 +1511,7 @@ static void test_uxtheme(void) dll_loaded = !!GetModuleHandleA("comctl32.dll"); ok(!dll_loaded, "Expected comctl32.dll not loaded.\n"); dll_loaded = !!GetModuleHandleA("uxtheme.dll"); + todo_wine_if(dll_loaded) ok(!dll_loaded, "Expected uxtheme.dll not loaded.\n");
/* Creating a window triggers uxtheme load when theming is active */ @@ -1531,7 +1532,6 @@ static void test_uxtheme(void) is_theme_active = pIsThemeActive(); FreeLibrary(uxtheme);
- todo_wine_if(is_theme_active) ok(dll_loaded == is_theme_active, "Expected uxtheme %s when theming is %s.\n", is_theme_active ? "loaded" : "not loaded", is_theme_active ? "active" : "inactive");