Themed Delphi applications use "explorer::listview" and "explorer::treeview": https://gitlab.com/freepascal.org/lazarus/lazarus/-/blob/main/lcl/interfaces...
-- v4: uxtheme: Parse app/class name in OpenThemeData(). uxtheme/tests: Add a test for OpenThemeData("explorer::treeview").
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/uxtheme/tests/system.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index c5fc19dd86a..f6b009f57ca 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -558,6 +558,11 @@ static void test_OpenThemeData(void)
/* Only do the next checks if we have an active theme */
+ hTheme = OpenThemeData(hWnd, L"dead:beef;explorer::treeview"); + todo_wine + ok(hTheme != NULL, "OpenThemeData() failed\n"); + CloseThemeData(hTheme); + SetLastError(0xdeadbeef); hTheme = OpenThemeData(hWnd, szButtonClassList); ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n"); @@ -2591,7 +2596,7 @@ static void test_theme(void) /* > XP use opaque scrollbar arrow parts, but TMT_TRANSPARENT is TRUE */ else { - ok(hr == S_OK, "Got unexpected hr %#lx,\n", hr); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(transparent, "Expected transparent.\n");
transparent = IsThemeBackgroundPartiallyTransparent(htheme, SBP_ARROWBTN, 0);
From: Dmitry Timoshkov dmitry@baikal.ru
Themed Delphi applications use "explorer::listview" and "explorer::treeview": https://gitlab.com/freepascal.org/lazarus/lazarus/-/blob/main/lcl/interfaces...
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/uxtheme/msstyles.c | 45 +++++++++++++++++++++++++++++++++---- dlls/uxtheme/tests/system.c | 1 - 2 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/dlls/uxtheme/msstyles.c b/dlls/uxtheme/msstyles.c index cfd21a48989..c2e68508088 100644 --- a/dlls/uxtheme/msstyles.c +++ b/dlls/uxtheme/msstyles.c @@ -1022,6 +1022,23 @@ static void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics) } }
+static void parse_app_class_name(LPCWSTR name, LPWSTR szAppName, LPWSTR szClassName) +{ + LPCWSTR p; + + szAppName[0] = szClassName[0] = 0; + + p = wcsstr(name, L"::"); + if (p) + { + lstrcpynW(szAppName, name, min(p - name + 1, MAX_THEME_APP_NAME)); + p += 2; + lstrcpynW(szClassName, p, min(wcslen(p) + 1, MAX_THEME_CLASS_NAME)); + } + else + lstrcpynW(szClassName, name, MAX_THEME_CLASS_NAME); +} + /*********************************************************************** * MSSTYLES_OpenThemeClass * @@ -1036,6 +1053,8 @@ static void MSSTYLES_ParseThemeIni(PTHEME_FILE tf, BOOL setMetrics) PTHEME_CLASS MSSTYLES_OpenThemeClass(LPCWSTR pszAppName, LPCWSTR pszClassList, UINT dpi) { PTHEME_CLASS cls = NULL; + WCHAR buf[MAX_THEME_APP_NAME + MAX_THEME_CLASS_NAME]; + WCHAR szAppName[MAX_THEME_APP_NAME]; WCHAR szClassName[MAX_THEME_CLASS_NAME]; LPCWSTR start; LPCWSTR end; @@ -1052,14 +1071,32 @@ PTHEME_CLASS MSSTYLES_OpenThemeClass(LPCWSTR pszAppName, LPCWSTR pszClassList, U start = pszClassList; while((end = wcschr(start, ';'))) { len = end-start; - lstrcpynW(szClassName, start, min(len+1, ARRAY_SIZE(szClassName))); + lstrcpynW(buf, start, min(len+1, ARRAY_SIZE(buf))); start = end+1; - cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName); + + parse_app_class_name(buf, szAppName, szClassName); + if (szAppName[0]) + { + /* If the application class is already set then fail */ + if (pszAppName) return NULL; + + cls = MSSTYLES_FindClass(tfActiveTheme, szAppName, szClassName); + } + else + cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName); if(cls) break; } if(!cls && *start) { - lstrcpynW(szClassName, start, ARRAY_SIZE(szClassName)); - cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName); + parse_app_class_name(start, szAppName, szClassName); + if (szAppName[0]) + { + /* If the application class is already set then fail */ + if (pszAppName) return NULL; + + cls = MSSTYLES_FindClass(tfActiveTheme, szAppName, szClassName); + } + else + cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName); } if(cls) { TRACE("Opened app %s, class %s from list %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName), debugstr_w(pszClassList)); diff --git a/dlls/uxtheme/tests/system.c b/dlls/uxtheme/tests/system.c index f6b009f57ca..55dd97f81e1 100644 --- a/dlls/uxtheme/tests/system.c +++ b/dlls/uxtheme/tests/system.c @@ -559,7 +559,6 @@ static void test_OpenThemeData(void) /* Only do the next checks if we have an active theme */
hTheme = OpenThemeData(hWnd, L"dead:beef;explorer::treeview"); - todo_wine ok(hTheme != NULL, "OpenThemeData() failed\n"); CloseThemeData(hTheme);
Zhiyi Zhang (@zhiyi) commented about dlls/uxtheme/tests/system.c:
/* Only do the next checks if we have an active theme */
- hTheme = OpenThemeData(hWnd, L"dead:beef;explorer::treeview");
Sorry if I gave you the wrong suggestion. But we should use :: between dead and beef.
Zhiyi Zhang (@zhiyi) commented about dlls/uxtheme/msstyles.c:
start = pszClassList; while((end = wcschr(start, ';'))) { len = end-start;
lstrcpynW(szClassName, start, min(len+1, ARRAY_SIZE(szClassName)));
lstrcpynW(buf, start, min(len+1, ARRAY_SIZE(buf))); start = end+1;
cls = MSSTYLES_FindClass(tfActiveTheme, pszAppName, szClassName);
parse_app_class_name(buf, szAppName, szClassName);
if (szAppName[0])
{
/* If the application class is already set then fail */
Please keep the tests for this case.
Zhiyi Zhang (@zhiyi) commented about dlls/uxtheme/msstyles.c:
}
}
+static void parse_app_class_name(LPCWSTR name, LPWSTR szAppName, LPWSTR szClassName)
It's a bit inconsistent that the function name uses underscores while its parameters use camelcase. Let's use the snake case here.
On Wed Nov 1 09:44:47 2023 +0000, Zhiyi Zhang wrote:
Sorry if I gave you the wrong suggestion. But we should use :: between dead and beef.
Please add checks for the last error code as well.