From f1e0eedcf501936e6b4f77b6fe3ac4997d757d94 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 1 Apr 2016 09:25:45 +0200 Subject: QWindowsXP/VistaStyle: Move the Vista treeview handling to QWindowsXPStylePrivate. QWindowsXPStylePrivate maintains a list of theme handles for various style items. The derived class QWindowsVistaStylePrivate had logic to use a special helper window with the "explorer" window theme set to obtain the correct treeview arrow branch indicator (arrow shape for Vista as opposed to '+'/'-' on Windows XP) when creating the "TREEVIEW" theme. This required calling the helper function QWindowsVistaStylePrivate::initTreeViewTheming() before QWindowsXPStylePrivate::createTheme(), which is prone to errors and initialization order issues. This could be solved by making QWindowsXPStylePrivate::createTheme() virtual or similar, but since it the fate of QWindowsXPStylePrivate is most likely to be merged into QWindowsVistaStylePrivate; it was decided to move the entire special handling of the Vista treeviews into QWindowsXPStylePrivate. The existing enumeration value QWindowsXPStylePrivate::TreeViewTheme is renamed to QWindowsXPStylePrivate::XpTreeViewTheme and a new value QWindowsXPStylePrivate::VistaTreeViewTheme is added for which QWindowsXPStylePrivate::createTheme() invokes the special handling. This also removes the need to destroy the helper window in unpolish(), which should save some initializations. Task-number: QTBUG-52230 Change-Id: I0492ecf38fb3e5eabc4ecbdef70f0bf05e82e104 Reviewed-by: Adam Light Reviewed-by: Joerg Bornemann --- src/widgets/styles/qwindowsvistastyle.cpp | 71 ++--------------------------- src/widgets/styles/qwindowsvistastyle_p_p.h | 8 +--- src/widgets/styles/qwindowsxpstyle.cpp | 62 ++++++++++++++++++++++++- src/widgets/styles/qwindowsxpstyle_p_p.h | 7 ++- 4 files changed, 72 insertions(+), 76 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 70623a9250..5e47c3267f 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -420,9 +420,9 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt case PE_IndicatorBranch: { - XPThemeData theme(widget, painter, QWindowsXPStylePrivate::TreeViewTheme); + XPThemeData theme(widget, painter, QWindowsXPStylePrivate::VistaTreeViewTheme); static int decoration_size = 0; - if (!decoration_size && d->initTreeViewTheming() && theme.isValid()) { + if (!decoration_size && theme.isValid()) { XPThemeData themeSize = theme; themeSize.partId = TVP_HOTGLYPH; themeSize.stateId = GLPS_OPENED; @@ -722,9 +722,9 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt QPainter pixmapPainter(&pixmap); XPThemeData theme(widget, &pixmapPainter, - QWindowsXPStylePrivate::TreeViewTheme, + QWindowsXPStylePrivate::VistaTreeViewTheme, LVP_LISTITEM, state, QRect(0, 0, sectionSize.width(), sectionSize.height())); - if (d->initTreeViewTheming() && theme.isValid()) { + if (theme.isValid()) { d->drawBackground(theme); } else { QWindowsXPStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget); @@ -2351,10 +2351,6 @@ void QWindowsVistaStyle::unpolish(QWidget *widget) QWindowsXPStyle::unpolish(widget); QWindowsVistaStylePrivate *d = d_func(); - // Delete the tree view helper in case the XP style cleaned the - // theme handle map due to a theme or QStyle change (QProxyStyle). - if (!QWindowsXPStylePrivate::hasTheme(QWindowsXPStylePrivate::TreeViewTheme)) - d->cleanupTreeViewTheming(); d->stopAnimation(widget); @@ -2420,15 +2416,10 @@ QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const } QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() : - QWindowsXPStylePrivate(), m_treeViewHelper(0) + QWindowsXPStylePrivate() { } -QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate() -{ - cleanupTreeViewTheming(); -} - bool QWindowsVistaStylePrivate::transitionsEnabled() const { BOOL animEnabled = false; @@ -2440,58 +2431,6 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const return false; } -/* - * We need to set the windows "explorer" theme explicitly on a native - * window and open the "TREEVIEW" theme handle passing its window handle - * in order to get Vista-style item view themes (particulary drawBackground() - * for selected items needs this). - * We invoke a service of the native Windows interface to create - * a non-visible window handle, open the theme on it and insert it into - * the cache so that it is found by XPThemeData::handle() first. - */ - -static inline HWND createTreeViewHelperWindow() -{ - if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) { - void *hwnd = 0; - void *wndProc = reinterpret_cast(DefWindowProc); - if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection, - Q_RETURN_ARG(void *, hwnd), - Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")), - Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")), - Q_ARG(void *, wndProc)) && hwnd) { - return reinterpret_cast(hwnd); - } - } - return 0; -} - -bool QWindowsVistaStylePrivate::initTreeViewTheming() -{ - if (m_treeViewHelper) - return true; - - m_treeViewHelper = createTreeViewHelperWindow(); - if (!m_treeViewHelper) { - qWarning("Unable to create the treeview helper window."); - return false; - } - const HRESULT hr = QWindowsXPStylePrivate::pSetWindowTheme(m_treeViewHelper, L"explorer", NULL); - if (hr != S_OK) { - qErrnoWarning("SetWindowTheme() failed."); - return false; - } - return QWindowsXPStylePrivate::createTheme(QWindowsXPStylePrivate::TreeViewTheme, m_treeViewHelper); -} - -void QWindowsVistaStylePrivate::cleanupTreeViewTheming() -{ - if (m_treeViewHelper) { - DestroyWindow(m_treeViewHelper); - m_treeViewHelper = 0; - } -} - /*! \reimp */ diff --git a/src/widgets/styles/qwindowsvistastyle_p_p.h b/src/widgets/styles/qwindowsvistastyle_p_p.h index 8a3cbe2b67..871962db0b 100644 --- a/src/widgets/styles/qwindowsvistastyle_p_p.h +++ b/src/widgets/styles/qwindowsvistastyle_p_p.h @@ -162,16 +162,10 @@ class QWindowsVistaStylePrivate : public QWindowsXPStylePrivate public: QWindowsVistaStylePrivate(); - ~QWindowsVistaStylePrivate(); + static int fixedPixelMetric(QStyle::PixelMetric pm); static inline bool useVista(); bool transitionsEnabled() const; - -private: - bool initTreeViewTheming(); - void cleanupTreeViewTheming(); - - HWND m_treeViewHelper; }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 2c98ebb740..fbf8a850fa 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include @@ -157,7 +159,7 @@ static const wchar_t *themeNames[QWindowsXPStylePrivate::NThemes] = 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"TREEVIEW", L"WINDOW", L"STATUS" + L"TREEVIEW", L"WINDOW", L"STATUS", L"TREEVIEW" }; static inline QBackingStore *backingStoreForWidget(const QWidget *widget) @@ -238,6 +240,7 @@ HRGN XPThemeData::mask(QWidget *widget) // QWindowsXPStylePrivate ------------------------------------------------------------------------- // Static initializations QPixmap *QWindowsXPStylePrivate::tabbody = 0; +HWND QWindowsXPStylePrivate::m_vistaTreeViewHelper = 0; HTHEME QWindowsXPStylePrivate::m_themes[NThemes]; bool QWindowsXPStylePrivate::use_xp = false; QBasicAtomicInt QWindowsXPStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting @@ -321,6 +324,58 @@ void QWindowsXPStylePrivate::cleanup(bool force) tabbody = 0; } +/* In order to obtain the correct VistaTreeViewTheme (arrows for PE_IndicatorBranch), + * we need to set the windows "explorer" theme explicitly on a native + * window and open the "TREEVIEW" theme handle passing its window handle + * in order to get Vista-style item view themes (particulary drawBackground() + * for selected items needs this). + * We invoke a service of the native Windows interface to create + * a non-visible window handle, open the theme on it and insert it into + * the cache so that it is found by XPThemeData::handle() first. + */ + +static inline HWND createTreeViewHelperWindow() +{ + if (QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface()) { + void *hwnd = 0; + void *wndProc = reinterpret_cast(DefWindowProc); + if (QMetaObject::invokeMethod(ni, "createMessageWindow", Qt::DirectConnection, + Q_RETURN_ARG(void *, hwnd), + Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindowClass")), + Q_ARG(QString, QStringLiteral("QTreeViewThemeHelperWindow")), + Q_ARG(void *, wndProc)) && hwnd) { + return reinterpret_cast(hwnd); + } + } + return 0; +} + +bool QWindowsXPStylePrivate::initVistaTreeViewTheming() +{ + if (m_vistaTreeViewHelper) + return true; + + m_vistaTreeViewHelper = createTreeViewHelperWindow(); + if (!m_vistaTreeViewHelper) { + qWarning("Unable to create the treeview helper window."); + return false; + } + if (FAILED(QWindowsXPStylePrivate::pSetWindowTheme(m_vistaTreeViewHelper, L"explorer", NULL))) { + qErrnoWarning("SetWindowTheme() failed."); + cleanupVistaTreeViewTheming(); + return false; + } + return true; +} + +void QWindowsXPStylePrivate::cleanupVistaTreeViewTheming() +{ + if (m_vistaTreeViewHelper) { + DestroyWindow(m_vistaTreeViewHelper); + m_vistaTreeViewHelper = 0; + } +} + /* \internal Closes all open theme data handles to ensure that we don't leak resources, and that we don't refere to old handles when for @@ -333,6 +388,7 @@ void QWindowsXPStylePrivate::cleanupHandleMap() pCloseThemeData(m_themes[i]); m_themes[i] = 0; } + QWindowsXPStylePrivate::cleanupVistaTreeViewTheming(); } HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd) @@ -343,6 +399,8 @@ HTHEME QWindowsXPStylePrivate::createTheme(int theme, HWND hwnd) } if (!m_themes[theme]) { const wchar_t *name = themeNames[theme]; + if (theme == VistaTreeViewTheme && QWindowsXPStylePrivate::initVistaTreeViewTheming()) + hwnd = QWindowsXPStylePrivate::m_vistaTreeViewHelper; m_themes[theme] = pOpenThemeData(hwnd, name); if (!m_themes[theme]) qErrnoWarning("OpenThemeData() failed for theme %d (%s).", @@ -1947,7 +2005,7 @@ case PE_Frame: bef_v -= delta; aft_h += delta; aft_v += delta; - XPThemeData theme(0, p, QWindowsXPStylePrivate::TreeViewTheme); + XPThemeData theme(0, p, QWindowsXPStylePrivate::XpTreeViewTheme); theme.rect = QRect(bef_h, bef_v, decoration_size, decoration_size); theme.partId = TVP_GLYPH; theme.stateId = flags & QStyle::State_Open ? GLPS_OPENED : GLPS_CLOSED; diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index d75c064369..51541ed218 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -350,9 +350,10 @@ public: ToolBarTheme, ToolTipTheme, TrackBarTheme, - TreeViewTheme, + XpTreeViewTheme, // '+'/'-' shape treeview indicators (XP) WindowTheme, StatusTheme, + VistaTreeViewTheme, // arrow shape treeview indicators (Vista) obtained from "explorer" theme. NThemes }; @@ -413,6 +414,9 @@ private: void showProperties(XPThemeData &themeData); #endif + static bool initVistaTreeViewTheming(); + static void cleanupVistaTreeViewTheming(); + static QBasicAtomicInt ref; static bool use_xp; static QPixmap *tabbody; @@ -424,6 +428,7 @@ private: uchar *bufferPixels; int bufferW, bufferH; + static HWND m_vistaTreeViewHelper; static HTHEME m_themes[NThemes]; }; -- cgit v1.2.3