1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwindowsthemecache_p.h"
#include <QtCore/qdebug.h>
#include <QtCore/qhash.h>
QT_BEGIN_NAMESPACE
// Theme names matching the QWindowsVistaStylePrivate::Theme enumeration.
constexpr const wchar_t *themeNames[] = {
L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW",
L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN",
L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR",
L"WINDOW", L"STATUS", L"TREEVIEW"
};
typedef std::array<HTHEME, std::size(themeNames)> ThemeArray;
typedef QHash<HWND, ThemeArray> ThemesCache;
Q_GLOBAL_STATIC(ThemesCache, themesCache);
QString QWindowsThemeCache::themeName(int theme)
{
return theme >= 0 && theme < int(std::size(themeNames))
? QString::fromWCharArray(themeNames[theme]) : QString();
}
HTHEME QWindowsThemeCache::createTheme(int theme, HWND hwnd)
{
if (Q_UNLIKELY(theme < 0 || theme >= int(std::size(themeNames)) || !hwnd)) {
qWarning("Invalid parameters #%d, %p", theme, hwnd);
return nullptr;
}
// Get or create themes array for this window.
ThemesCache *cache = themesCache();
auto it = cache->find(hwnd);
if (it == cache->end())
it = cache->insert(hwnd, ThemeArray {});
// Get or create theme data
ThemeArray &themes = *it;
if (!themes[theme]) {
const wchar_t *name = themeNames[theme];
themes[theme] = OpenThemeData(hwnd, name);
if (Q_UNLIKELY(!themes[theme]))
qErrnoWarning("OpenThemeData() failed for theme %d (%s).",
theme, qPrintable(themeName(theme)));
}
return themes[theme];
}
static void clearThemes(ThemeArray &themes)
{
for (auto &theme : themes) {
if (theme) {
CloseThemeData(theme);
theme = nullptr;
}
}
}
void QWindowsThemeCache::clearThemeCache(HWND hwnd)
{
ThemesCache *cache = themesCache();
auto it = cache->find(hwnd);
if (it == cache->end())
return;
clearThemes(*it);
}
void QWindowsThemeCache::clearAllThemeCaches()
{
ThemesCache *cache = themesCache();
for (auto &themeArray : *cache)
clearThemes(themeArray);
}
QT_END_NAMESPACE
|