Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwindowswindowclassregistry.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
7#include <QtCore/qlibraryinfo.h>
8#include <QtCore/quuid.h>
9
12
13QT_BEGIN_NAMESPACE
14
15using namespace Qt::StringLiterals;
16
17Q_LOGGING_CATEGORY(lcQpaWindowClass, "qt.qpa.windowclass")
18
20
21QWindowsWindowClassRegistry::QWindowsWindowClassRegistry(WNDPROC defaultProcedure)
22 : m_defaultProcedure(defaultProcedure)
23{
24 m_instance = this;
25}
26
28{
29 unregisterWindowClasses();
30
31 m_instance = nullptr;
32}
33
38
39QString QWindowsWindowClassRegistry::classNamePrefix()
40{
41 static QString result;
42 if (result.isEmpty()) {
43 QTextStream str(&result);
44 str << "Qt" << QT_VERSION_MAJOR << QT_VERSION_MINOR << QT_VERSION_PATCH;
45 if (QLibraryInfo::isDebugBuild())
46 str << 'd';
47#ifdef QT_NAMESPACE
48# define xstr(s) str(s)
49# define str(s) #s
50 str << xstr(QT_NAMESPACE);
51# undef str
52# undef xstr
53#endif
54 }
55 return result;
56}
57
59{
60 QString className = description.name;
61
62 if (description.shouldAddPrefix)
63 className = classNamePrefix() + className;
64
65 // since multiple Qt versions can be used in one process
66 // each one has to have window class names with a unique name
67 // The first instance gets the unmodified name; if the class
68 // has already been registered by another instance of Qt then
69 // add a UUID. The check needs to be performed for each name
70 // in case new message windows are added (QTBUG-81347).
71 // Note: GetClassInfo() returns != 0 when a class exists.
72 if (shouldDecorateWindowClassName(description))
73 className += QUuid::createUuid().toString();
74
75 if (m_registeredWindowClassNames.contains(className)) // already registered in our list
76 return className;
77
78 const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
79
80 WNDCLASSEX wc{};
81 wc.cbSize = sizeof(WNDCLASSEX);
82 wc.style = description.style;
83 wc.lpfnWndProc = description.procedure;
84 wc.hInstance = appInstance;
85 wc.hbrBackground = description.brush;
86 if (description.hasIcon) {
87 wc.hIcon = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE));
88 if (wc.hIcon) {
89 int sw = GetSystemMetrics(SM_CXSMICON);
90 int sh = GetSystemMetrics(SM_CYSMICON);
91 wc.hIconSm = static_cast<HICON>(LoadImage(appInstance, L"IDI_ICON1", IMAGE_ICON, sw, sh, 0));
92 }
93 else {
94 wc.hIcon = static_cast<HICON>(LoadImage(nullptr, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED));
95 }
96 }
97
98 wc.lpszClassName = reinterpret_cast<LPCWSTR>(className.utf16());
99 ATOM atom = RegisterClassEx(&wc);
100 if (!atom)
101 qCWarning(lcQpaWindowClass) << "Failed to register window class" << className
102 << "(" << qt_error_string(-1) << ")";
103
104 m_registeredWindowClassNames.insert(className);
105
106 qCDebug(lcQpaWindowClass).nospace() << __FUNCTION__ << ' ' << className << ' ' << description << " atom=" << atom;
107
108 return className;
109}
110
112{
113 return registerWindowClass(QWindowsWindowClassDescription::fromWindow(window, m_defaultProcedure));
114}
115
117{
118 return registerWindowClass(QWindowsWindowClassDescription::fromName(name, procedure));
119}
120
121bool QWindowsWindowClassRegistry::shouldDecorateWindowClassName(const QWindowsWindowClassDescription &description) const
122{
123 return shouldDecorateWindowClassName(description.name, description.procedure);
124}
125
126bool QWindowsWindowClassRegistry::shouldDecorateWindowClassName(const QString &name, WNDPROC procedure) const
127{
128 const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
129
130 WNDCLASS wc{};
131
132 return GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(name.utf16()), &wc) != FALSE
133 && wc.lpfnWndProc != procedure;
134}
135
136void QWindowsWindowClassRegistry::unregisterWindowClasses()
137{
138 const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
139
140 for (const QString &name : std::as_const(m_registeredWindowClassNames)) {
141 if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose)
142 qCWarning(lcQpaWindowClass) << "Failed to unregister window class" << name
143 << "(" << qt_error_string(-1) << ")";
144 }
145 m_registeredWindowClassNames.clear();
146}
147
148QT_END_NAMESPACE
QString registerWindowClass(const QWindowsWindowClassDescription &description)
static QWindowsWindowClassRegistry * instance()
QString registerWindowClass(QString name, WNDPROC procedure)
QString registerWindowClass(const QWindow *window)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")