Windows styles: Add device pixel scaling for system metrics.

Metrics obtained from the system must be scaled down
when device pixel ration scaling is in effect. Factor out
functions to return the device pixel values which might still
be used for drawing.

Task-number: QTBUG-38993
Task-number: QTBUG-38858
Change-Id: I6b90629e4979436bbb46f8c1fa1ee2253ada7ece
Reviewed-by: Alessandro Portale <alessandro.portale@digia.com>
This commit is contained in:
Friedemann Kleint 2014-08-29 17:38:25 +02:00
parent b858e7af4f
commit 176bd1edfa
5 changed files with 291 additions and 297 deletions

View File

@ -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;

View File

@ -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

View File

@ -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<qint32>(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<const QStyleOptionMenuItem *>(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);

View File

@ -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<const QStyleOptionSizeGrip *>(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<const QStyleOptionProgressBarV2 *>(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<const QListView*>(widget))
res = 2;
else
res = 1;
res = qobject_cast<const QListView*>(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<const QStyleOptionProgressBarV2 *>(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<const QStyleOptionToolButton *>(option))
res = 1;
else
res = 0;
break;
case PM_ButtonDefaultIndicator:
res = 0;
res = qstyleoption_cast<const QStyleOptionToolButton *>(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);

View File

@ -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