diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index cf0afd8031..44242177dc 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -118,6 +118,9 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; /* \internal */ + +int QWindowsStylePrivate::m_appDevicePixelRatio = 0; + QWindowsStylePrivate::QWindowsStylePrivate() : alt_down(false), menuBarTimer(0) { @@ -130,6 +133,13 @@ QWindowsStylePrivate::QWindowsStylePrivate() #endif } +int QWindowsStylePrivate::appDevicePixelRatio() +{ + if (!QWindowsStylePrivate::m_appDevicePixelRatio) + QWindowsStylePrivate::m_appDevicePixelRatio = qRound(qApp->devicePixelRatio()); + return QWindowsStylePrivate::m_appDevicePixelRatio; +} + // Returns \c true if the toplevel parent of \a widget has seen the Alt-key bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const { @@ -295,19 +305,76 @@ void QWindowsStyle::polish(QPalette &pal) QCommonStyle::polish(pal); } +int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget) +{ + switch (pm) { +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + case QStyle::PM_DockWidgetFrameWidth: +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CXFRAME); +# else + return GetSystemMetrics(SM_CXDLGFRAME); +# endif + break; + + case QStyle::PM_TitleBarHeight: + if (widget && (widget->windowType() == Qt::Tool)) { + // MS always use one less than they say +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CYSMCAPTION) - 1; +# else + return GetSystemMetrics(SM_CYCAPTION) - 1; +# endif + } + return GetSystemMetrics(SM_CYCAPTION) - 1; + +# ifndef Q_OS_WINCE + case QStyle::PM_ScrollBarExtent: + { + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) + return qMax(ncm.iScrollHeight, ncm.iScrollWidth); + } + break; +# endif // !Q_OS_WINCE + + case QStyle::PM_MdiSubWindowFrameWidth: +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CYFRAME); +# else + return GetSystemMetrics(SM_CYDLGFRAME); +# endif +#else + Q_UNUSED(widget) +#endif // Q_OS_WIN + + default: + break; + } + return QWindowsStylePrivate::InvalidMetric; +} + /*! \reimp */ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const { - int ret; + int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget); + if (ret != QWindowsStylePrivate::InvalidMetric) + return ret / QWindowsStylePrivate::devicePixelRatio(widget); + + ret = 0; switch (pm) { + case PM_ToolBarItemSpacing: + break; case PM_ButtonDefaultIndicator: case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: case PM_MenuHMargin: case PM_MenuVMargin: + case PM_ToolBarItemMargin: ret = 1; break; case PM_DockWidgetSeparatorExtent: @@ -315,7 +382,6 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW break; #ifndef QT_NO_TABBAR case PM_TabBarTabShiftHorizontal: - ret = 0; break; case PM_TabBarTabShiftVertical: ret = 2; @@ -357,23 +423,14 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW if (space > 0) thick += (space * 2) / (n + 2); ret = thick; - } else { - ret = 0; } break; #endif // QT_NO_SLIDER #ifndef QT_NO_MENU case PM_MenuBarHMargin: - ret = 0; - break; - case PM_MenuBarVMargin: - ret = 0; - break; - case PM_MenuBarPanelWidth: - ret = 0; break; case PM_SmallIconSize: @@ -394,76 +451,16 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW case PM_DockWidgetTitleBarButtonMargin: ret = int(QStyleHelper::dpiScaled(4.)); break; -#if defined(Q_WS_WIN) - case PM_DockWidgetFrameWidth: -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CXDLGFRAME); -#else - ret = GetSystemMetrics(SM_CXFRAME); -#endif - break; -#else case PM_DockWidgetFrameWidth: ret = 4; break; -#endif // Q_WS_WIN break; #endif // QT_NO_MENU - - -#if defined(Q_OS_WIN) -#ifndef Q_OS_WINRT // There is no title bar in Windows Runtime applications - case PM_TitleBarHeight: - if (widget && (widget->windowType() == Qt::Tool)) { - // MS always use one less than they say -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CYCAPTION) - 1; -#else - ret = GetSystemMetrics(SM_CYSMCAPTION) - 1; -#endif - } else { - ret = GetSystemMetrics(SM_CYCAPTION) - 1; - } - - break; -#endif // !Q_OS_WINRT - - case PM_ScrollBarExtent: - { -#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) - ret = qMax(ncm.iScrollHeight, ncm.iScrollWidth); - else -#endif // !Q_OS_WINCE && !Q_OS_WINRT - ret = QCommonStyle::pixelMetric(pm, opt, widget); - } - break; -#endif // Q_OS_WIN - case PM_SplitterWidth: ret = qMax(4, QApplication::globalStrut().width()); break; -#if defined(Q_OS_WIN) -#ifndef Q_OS_WINRT // Mdi concept not available for WinRT applications - case PM_MdiSubWindowFrameWidth: -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CYDLGFRAME); -#else - ret = GetSystemMetrics(SM_CYFRAME); -#endif - break; -#endif // !Q_OS_WINRT -#endif // Q_OS_WIN - case PM_ToolBarItemMargin: - ret = 1; - break; - case PM_ToolBarItemSpacing: - ret = 0; - break; case PM_ToolBarHandleExtent: ret = int(QStyleHelper::dpiScaled(10.)); break; diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h index 872b6f0e9e..8f70271357 100644 --- a/src/widgets/styles/qwindowsstyle_p_p.h +++ b/src/widgets/styles/qwindowsstyle_p_p.h @@ -68,7 +68,13 @@ class QWindowsStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QWindowsStyle) public: + enum { InvalidMetric = -23576 }; + QWindowsStylePrivate(); + static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static int devicePixelRatio(const QWidget *widget = 0) + { return widget ? widget->devicePixelRatio() : QWindowsStylePrivate::appDevicePixelRatio(); } + bool hasSeenAlt(const QWidget *widget) const; bool altDown() const { return alt_down; } bool alt_down; @@ -90,6 +96,10 @@ public: windowsRightBorder = 15, // right border on windows windowsCheckMarkWidth = 12 // checkmarks width on windows }; + +private: + static int appDevicePixelRatio(); + static int m_appDevicePixelRatio; }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 672f5c78ac..69e21d0f56 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -409,9 +409,11 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt XPThemeData theme(0, painter, QWindowsXPStylePrivate::TreeViewTheme); static int decoration_size = 0; if (d->initTreeViewTheming() && theme.isValid() && !decoration_size) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size); - decoration_size = qMax(size.cx, size.cy); + XPThemeData themeSize = theme; + themeSize.partId = TVP_HOTGLYPH; + themeSize.stateId = GLPS_OPENED; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + decoration_size = qMax(size.width(), size.height()); } int mid_h = option->rect.x() + option->rect.width() / 2; int mid_v = option->rect.y() + option->rect.height() / 2; @@ -990,10 +992,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme, TP_DROPDOWNBUTTON); if (theme.isValid()) { - SIZE size; - if (QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { - mbiw = size.cx; - mbih = size.cy; + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!size.isEmpty()) { + mbiw = size.width(); + mbih = size.height(); } } QRect ir = subElementRect(SE_PushButtonContents, option, 0); @@ -1183,13 +1185,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption // windows always has a check column, regardless whether we have an icon or not int checkcol = 25; { - SIZE size; - MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); - checkcol = qMax(menuitem->maxIconWidth, int(3 + size.cx + margins.cxLeftWidth + margins.cxRightWidth)); + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + checkcol = qMax(menuitem->maxIconWidth, int(3 + size.width() + margins.left() + margins.right())); } QRect rect = option->rect; @@ -1241,20 +1244,20 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect); - SIZE size; - MARGINS margins; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, - TMT_CONTENTMARGINS, NULL, &margins); - QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth , - size.cy + margins.cyBottomHeight + margins.cyTopHeight); + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QRect checkRect(0, 0, size.width() + margins.left() + margins.right(), + size.height() + margins.bottom() + margins.top()); checkRect.moveCenter(vCheckRect.center()); theme.rect = checkRect; d->drawBackground(theme); if (menuitem->icon.isNull()) { - checkRect = QRect(0, 0, size.cx, size.cy); + checkRect = QRect(QPoint(0, 0), size); checkRect.moveCenter(theme.rect.center()); theme.rect = checkRect; @@ -1763,29 +1766,21 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle const int swidth = theme.rect.width(); const int sheight = theme.rect.height(); - MARGINS contentsMargin; - RECT rect = theme.toRECT(theme.rect); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + const QMargins contentsMargin = theme.margins(theme.rect, TMT_SIZINGMARGINS) + / QWindowsXPStylePrivate::devicePixelRatio(widget); - SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - int gw = size.cx, gh = size.cy; - + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) { - QRect gripperBounds; - if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); - } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); + QPoint gripperBoundsPos(0, 0); + if ((flags & State_Horizontal + && swidth - contentsMargin.left() - contentsMargin.right() > size.width()) + || sheight - contentsMargin.top() - contentsMargin.bottom() > size.height()) { + gripperBoundsPos = QPoint(theme.rect.left() + (swidth - size.width()) / 2, + theme.rect.top() + (sheight - size.height()) / 2); } + const QRect gripperBounds(gripperBoundsPos, size); // Draw gripper if there is enough space if (!gripperBounds.isEmpty() && flags & State_Enabled) { @@ -1883,15 +1878,16 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); int minimumHeight; { - SIZE size; - MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); - minimumHeight = qMax(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height()); - sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth; + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + minimumHeight = qMax(size.height() + margins.bottom() + margins.top(), sz.height()); + sz.rwidth() += size.width() + margins.left() + margins.right(); } if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { @@ -1999,10 +1995,10 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int arrowWidth = 13; int arrowHeight = 5; if (theme.isValid()) { - SIZE size; - if (QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { - arrowWidth = size.cx; - arrowHeight = size.cy; + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!size.isEmpty()) { + arrowWidth = size.width(); + arrowHeight = size.height(); } } if (option->state & State_Horizontal) { @@ -2195,7 +2191,8 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - 4; const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; @@ -2531,14 +2528,13 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon, QWindowsXPStylePrivate::ButtonTheme, BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); QIcon linkGlyph; - QPixmap pm = QPixmap(size.cx, size.cy); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 2e3586db42..424a1f7234 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -411,22 +411,21 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) height of the screen. This way the theme engine doesn't need to scale the body for every time we ask for it. (Speed optimization) */ -const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *) +const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget) { if (!tabbody) { - SIZE sz; XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY); - pGetThemePartSize(theme.handle(), qt_win_display_dc(), TABP_BODY, 0, 0, TS_TRUE, &sz); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); - tabbody = new QPixmap(sz.cx, QApplication::desktop()->screenGeometry().height()); + tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height()); QPainter painter(tabbody); - theme.rect = QRect(0, 0, sz.cx, sz.cy); + theme.rect = QRect(QPoint(0, 0), size); drawBackground(theme); // We fill with the last line of the themedata, that // way we don't get a tiled pixmap inside big tabs - QPixmap temp(sz.cx, 1); - painter.drawPixmap(0, 0, temp, 0, sz.cy-1, -1, -1); - painter.drawTiledPixmap(0, sz.cy, sz.cx, tabbody->height()-sz.cy, temp); + QPixmap temp(size.width(), 1); + painter.drawPixmap(0, 0, temp, 0, size.height() - 1, -1, -1); + painter.drawTiledPixmap(0, size.height(), size.width(), tabbody->height() - size.height(), temp); } return tabbody; } @@ -2002,25 +2001,24 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op { themeNumber = QWindowsXPStylePrivate::StatusTheme; partId = SP_GRIPPER; - SIZE sz; XPThemeData theme(0, p, themeNumber, partId, 0); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, partId, 0, 0, TS_TRUE, &sz); - --sz.cy; + QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + size.rheight()--; if (const QStyleOptionSizeGrip *sg = qstyleoption_cast(option)) { switch (sg->corner) { case Qt::BottomRightCorner: - rect = QRect(rect.right() - sz.cx, rect.bottom() - sz.cy, sz.cx, sz.cy); + rect = QRect(QPoint(rect.right() - size.width(), rect.bottom() - size.height()), size); break; case Qt::BottomLeftCorner: - rect = QRect(rect.left() + 1, rect.bottom() - sz.cy, sz.cx, sz.cy); + rect = QRect(QPoint(rect.left() + 1, rect.bottom() - size.height()), size); hMirrored = true; break; case Qt::TopRightCorner: - rect = QRect(rect.right() - sz.cx, rect.top() + 1, sz.cx, sz.cy); + rect = QRect(QPoint(rect.right() - size.width(), rect.top() + 1), size); vMirrored = true; break; case Qt::TopLeftCorner: - rect = QRect(rect.left() + 1, rect.top() + 1, sz.cx, sz.cy); + rect = QRect(rect.topLeft() + QPoint(1, 1), size); hMirrored = vMirrored = true; } } @@ -2075,10 +2073,9 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op QWindowsXPStylePrivate::ToolBarTheme, TP_SPLITBUTTONDROPDOWN); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - mbiw = size.cx; - mbih = size.cy; + const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + mbiw = size.width(); + mbih = size.height(); } QRect ir = btn->rect; @@ -2770,28 +2767,19 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo const int swidth = theme.rect.width(); const int sheight = theme.rect.height(); - MARGINS contentsMargin; - RECT rect = theme.toRECT(theme.rect); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + const QMargins contentsMargin = theme.margins(theme.rect, TMT_SIZINGMARGINS) + / QWindowsStylePrivate::devicePixelRatio(widget); - SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - int gw = size.cx, gh = size.cy; - - - QRect gripperBounds; - if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); - } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); + const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QPoint gripperBoundsPos(0, 0); + if ((flags & State_Horizontal + && swidth - contentsMargin.left() - contentsMargin.right() > size.width()) + || sheight - contentsMargin.top() - contentsMargin.bottom() > size.height()) { + gripperBoundsPos = QPoint(theme.rect.left() + (swidth - size.width()) / 2, + theme.rect.top() + (sheight - size.height()) /2); } + const QRect gripperBounds(gripperBoundsPos, size); // Draw gripper if there is enough space if (!gripperBounds.isEmpty()) { @@ -3113,9 +3101,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } else { theme.partId = partId; theme.stateId = stateId; - SIZE sz; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz); - if (sz.cx == 0 || sz.cy == 0) { + if (theme.size().isEmpty()) { int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize); p->save(); @@ -3330,23 +3316,63 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } } +static inline Qt::Orientation progressBarOrientation(const QStyleOption *option = 0) +{ + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) + return pb2->orientation; + return Qt::Horizontal; +} + +int QWindowsXPStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option, const QWidget *widget) +{ + switch (pm) { + case QStyle::PM_IndicatorWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).width(); + case QStyle::PM_IndicatorHeight: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).height(); + case QStyle::PM_ExclusiveIndicatorWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).width(); + case QStyle::PM_ExclusiveIndicatorHeight: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).height(); + case QStyle::PM_ProgressBarChunkWidth: + return progressBarOrientation(option) == Qt::Horizontal + ? XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNK).width() + : XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNKVERT).height(); + case QStyle::PM_SliderThickness: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::TrackBarTheme, TKP_THUMB).height(); + case QStyle::PM_TitleBarHeight: + return widget && (widget->windowType() == Qt::Tool) + ? GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME) + : GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); + case QStyle::PM_MdiSubWindowFrameWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE).width(); + case QStyle::PM_DockWidgetFrameWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE).width(); + default: + break; + } + return QWindowsXPStylePrivate::InvalidMetric; +} + /*! \reimp */ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, const QWidget *widget) const { if (!QWindowsXPStylePrivate::useXP()) return QWindowsStyle::pixelMetric(pm, option, widget); - int res = 0; + int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget); + if (res != QWindowsStylePrivate::InvalidMetric) + return res / QWindowsStylePrivate::devicePixelRatio(widget); + + res = 0; switch (pm) { case PM_MenuBarPanelWidth: + case PM_ButtonDefaultIndicator: res = 0; break; case PM_DefaultFrameWidth: - if (qobject_cast(widget)) - res = 2; - else - res = 1; + res = qobject_cast(widget) ? 2 : 1; break; case PM_MenuPanelWidth: case PM_SpinBoxFrameWidth: @@ -3364,6 +3390,8 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con switch (tab->shape) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: res = 1; break; case QTabBar::RoundedSouth: @@ -3374,10 +3402,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con case QTabBar::TriangularEast: res = 3; break; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - res = 1; - break; } } break; @@ -3386,77 +3410,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con res = qMax(int(QStyleHelper::dpiScaled(5.)), QApplication::globalStrut().width()); break; - case PM_IndicatorWidth: - case PM_IndicatorHeight: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (pm == PM_IndicatorWidth) ? size.cx : size.cy; - } - } - break; - - case PM_ExclusiveIndicatorWidth: - case PM_ExclusiveIndicatorHeight: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (pm == PM_ExclusiveIndicatorWidth) ? size.cx : size.cy; - } - } - break; - - case PM_ProgressBarChunkWidth: - { - Qt::Orientation orient = Qt::Horizontal; - if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast(option)) - orient = pb2->orientation; - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ProgressTheme, - (orient == Qt::Horizontal) ? PP_CHUNK : PP_CHUNKVERT); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (orient == Qt::Horizontal) ? size.cx : size.cy; - } - } - break; - - case PM_SliderThickness: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::TrackBarTheme, - TKP_THUMB); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cy; - } - } - break; - - case PM_TitleBarHeight: - { - if (widget && (widget->windowType() == Qt::Tool)) - res = GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - else - res = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - } - break; - - case PM_MdiSubWindowFrameWidth: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size); - res = size.cx-1; - } - } - break; - case PM_MdiSubWindowMinimizedWidth: res = 160; break; @@ -3467,33 +3420,14 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con break; #endif // QT_NO_TOOLBAR - case PM_DockWidgetFrameWidth: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cx; - } - } - break; case PM_DockWidgetSeparatorExtent: - res = int(QStyleHelper::dpiScaled(4.)); - break; case PM_DockWidgetTitleMargin: res = int(QStyleHelper::dpiScaled(4.)); break; case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: - if (qstyleoption_cast(option)) - res = 1; - else - res = 0; - break; - - case PM_ButtonDefaultIndicator: - res = 0; + res = qstyleoption_cast(option) ? 1 : 0; break; default: @@ -3573,8 +3507,11 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - int buttonHeight = GetSystemMetrics(SM_CYSIZE) - 4; - int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + const int buttonMargin = 4; + int buttonHeight = GetSystemMetrics(SM_CYSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - buttonMargin; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - buttonMargin; const int delta = buttonWidth + 2; int controlTop = option->rect.bottom() - buttonHeight - 2; const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); @@ -3766,20 +3703,12 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt case CT_LineEdit: case CT_ComboBox: { - XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme); - HTHEME theme = buttontheme.handle(); - MARGINS borderSize; - if (theme) { - int result = QWindowsXPStylePrivate::pGetThemeMargins(theme, - NULL, - BP_PUSHBUTTON, - PBS_NORMAL, - TMT_CONTENTMARGINS, - NULL, - &borderSize); - if (result == S_OK) { - sz += QSize(borderSize.cxLeftWidth + borderSize.cxRightWidth - 2, - borderSize.cyBottomHeight + borderSize.cyTopHeight - 2); + XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); + if (buttontheme.isValid()) { + const QMargins borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!borderSize.isNull()) { + sz.rwidth() += borderSize.left() + borderSize.right() - 2; + sz.rheight() += borderSize.bottom() + borderSize.top() - 2; } const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) @@ -3949,9 +3878,8 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt if (widget && widget->isWindow()) { XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - SIZE sz; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &sz); - return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(QSize(sz.cx, sz.cy)); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size); } } } @@ -3984,13 +3912,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_MAXBUTTON, MAXBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); @@ -4019,14 +3946,13 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; theme.partId = WP_CLOSEBUTTON; // #### - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); @@ -4056,13 +3982,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_RESTOREBUTTON, RBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 190055b24b..0ead58393f 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -219,9 +219,19 @@ public: HRGN mask(QWidget *widget); HTHEME handle(); - RECT toRECT(const QRect &qr); + static RECT toRECT(const QRect &qr); bool isValid(); + QSize size(); + QMargins margins(const QRect &rect, int propId = TMT_CONTENTMARGINS); + QMargins margins(int propId = TMT_CONTENTMARGINS); + + static QSize themeSize(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, int part = 0, int state = 0); + static QMargins themeMargins(const QRect &rect, const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, + int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); + static QMargins themeMargins(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, + int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); + const QWidget *widget; QPainter *painter; @@ -374,6 +384,8 @@ public: ~QWindowsXPStylePrivate() { cleanup(); } + static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static HWND winId(const QWidget *widget); void init(bool force = false); @@ -432,6 +444,60 @@ private: static HTHEME m_themes[NThemes]; }; +inline QSize XPThemeData::size() +{ + QSize result(0, 0); + if (isValid()) { + SIZE size; + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemePartSize(handle(), 0, partId, stateId, 0, TS_TRUE, &size))) + result = QSize(size.cx, size.cy); + } + return result; +} + +inline QMargins XPThemeData::margins(const QRect &qRect, int propId) +{ + QMargins result(0, 0, 0 ,0); + if (isValid()) { + MARGINS margins; + RECT rect = XPThemeData::toRECT(qRect); + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, &rect, &margins))) + result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); + } + return result; +} + +inline QMargins XPThemeData::margins(int propId) +{ + QMargins result(0, 0, 0 ,0); + if (isValid()) { + MARGINS margins; + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, NULL, &margins))) + result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); + } + return result; +} + +inline QSize XPThemeData::themeSize(const QWidget *w, QPainter *p, int themeIn, int part, int state) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.size(); +} + +inline QMargins XPThemeData::themeMargins(const QRect &rect, const QWidget *w, QPainter *p, int themeIn, + int part, int state, int propId) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.margins(rect, propId); +} + +inline QMargins XPThemeData::themeMargins(const QWidget *w, QPainter *p, int themeIn, + int part, int state, int propId) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.margins(propId); +} + #endif // QT_NO_STYLE_WINDOWS QT_END_NAMESPACE