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/qwindowsxpstyle.cpp | 62 ++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) (limited to 'src/widgets/styles/qwindowsxpstyle.cpp') 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; -- cgit v1.2.3 From cec15a89d058424794978910cc8da65b43d71606 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 8 Apr 2016 14:11:48 +0200 Subject: QWindowsXPStyle: Enlarge QLineEdit/QComboBox when High DPI scaling is active. In QWindowsXPStyle::sizeFromContents(), scale the margins using the devicePixelRatio and round the height up. Typically increases the height by 2 pixels when the device pixel ratio equals 2. Change-Id: I446ad518c3808a6454a08db7b66a942d37c1703f Task-number: QTBUG-49374 Reviewed-by: Alessandro Portale --- src/widgets/styles/qwindowsxpstyle.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/widgets/styles/qwindowsxpstyle.cpp') diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index fbf8a850fa..e9415f4292 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -3793,10 +3793,12 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt { XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); if (buttontheme.isValid()) { - const QMarginsF borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const qreal devicePixelRatio = QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF borderSize = buttontheme.margins() / devicePixelRatio; if (!borderSize.isNull()) { - sz.rwidth() += qRound(borderSize.left() + borderSize.right() - 2); - sz.rheight() += qRound(borderSize.bottom() + borderSize.top() - 2); + const qreal margin = qreal(2) / devicePixelRatio; + sz.rwidth() += qRound(borderSize.left() + borderSize.right() - margin); + sz.rheight() += int(borderSize.bottom() + borderSize.top() - margin + devicePixelRatio - 1); } const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) -- cgit v1.2.3