📄 qwindowsxpstyle.cpp
字号:
DTBGOPTS drawOptions; drawOptions.dwSize = sizeof(drawOptions); drawOptions.rcClip = themeData.toRECT(rect); drawOptions.dwFlags = DTBG_CLIPRECT | (themeData.noBorder ? DTBG_OMITBORDER : 0) | (themeData.noContent ? DTBG_OMITCONTENT : 0); // Drawing the part into the backing store if (pDrawThemeBackgroundEx != 0) { pDrawThemeBackgroundEx(themeData.handle(), dc, themeData.partId, themeData.stateId, &(themeData.toRECT(area)), &drawOptions); } else { // Set the clip region, if used.. if (addBorderContentClipping) { SelectClipRgn(dc, extraClip.handle()); // Compensate for the noBorder area difference (noContent has the same area) drawOptions.rcClip = themeData.toRECT(rect.adjusted(dx, dy, dr, db)); } pDrawThemeBackground(themeData.handle(), dc, themeData.partId, themeData.stateId, &(drawOptions.rcClip), 0); if (addBorderContentClipping) SelectClipRgn(dc, 0); } // If not cached, analyze the buffer data to figure // out alpha type, and if it contains data if (!isCached) { if (inspectData) stateHasData = hasAnyData(rect); // SHORTCUT: If the part's state has no data, cache it for NOOP later if (!stateHasData) { memset(&data, 0, sizeof(data)); data.dataValid = true; alphaCache.insert(key, data); return; } hasAlpha = hasAlphaChannel(rect);#if defined(DEBUG_XP_STYLE) && 1 dumpNativeDIB(w, h);#endif } // Swap alpha values, if needed if (inspectData) wasAlphaSwapped = swapAlphaChannel(rect); // Fix alpha values, if needed if (potentialInvalidAlpha) wasAlphaFixed = fixAlphaChannel(rect); QImage::Format format; if ((partIsTransparent && !wasAlphaSwapped) || (!partIsTransparent && hasAlpha)) { format = QImage::Format_ARGB32_Premultiplied; alphaType = RealAlpha; } else if (wasAlphaSwapped) { format = QImage::Format_ARGB32_Premultiplied; alphaType = MaskAlpha; } else { format = QImage::Format_RGB32; alphaType = NoAlpha; }#if defined(DEBUG_XP_STYLE) && 1 printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha");#endif img = QImage(bufferPixels, bufferW, bufferH, format); } // Blitting backing store bool useRegion = partIsTransparent && !hasAlpha && !wasAlphaSwapped; QRegion newRegion; QRegion oldRegion; if (useRegion) { newRegion = region(themeData); oldRegion = painter->clipRegion(); painter->setClipRegion(newRegion);#if defined(DEBUG_XP_STYLE) && 0 printf("Using region:\n"); QVector<QRect> rects = newRegion.rects(); for (int i = 0; i < rects.count(); ++i) { const QRect &r = rects.at(i); printf(" (%d, %d, %d, %d)\n", r.x(), r.y(), r.right(), r.bottom()); }#endif } if (addBorderContentClipping) painter->setClipRegion(extraClip, Qt::IntersectClip); if (!themeData.mirrorHorizontally && !themeData.mirrorVertically && !themeData.rotate) { if (!haveCachedPixmap) painter->drawImage(themeData.rect, img, rect); else painter->drawPixmap(themeData.rect, cachedPixmap); } else { // This is _slow_! // Make a copy containing only the necessary data, and mirror // on all wanted axes. Then draw the copy. // If cached, the normal pixmap is cached, instead of caching // all possible orientations for each part and state. QImage imgCopy; if (!haveCachedPixmap) imgCopy = img.copy(rect); else imgCopy = cachedPixmap.toImage(); if (themeData.rotate) { QMatrix rotMatrix; rotMatrix.rotate(themeData.rotate); imgCopy = imgCopy.transformed(rotMatrix); } if (themeData.mirrorHorizontally || themeData.mirrorVertically) { imgCopy = imgCopy.mirrored(themeData.mirrorHorizontally, themeData.mirrorVertically); } painter->drawImage(themeData.rect, imgCopy); } if (useRegion || addBorderContentClipping) { if (oldRegion.isEmpty()) painter->setClipping(false); else painter->setClipRegion(oldRegion); } // Cache the pixmap to avoid expensive swapAlphaChannel() calls if (!haveCachedPixmap && ((w * h) < 2000) && w && h) { QPixmap pix = QPixmap::fromImage(img).copy(rect); QPixmapCache::insert(pixmapCacheKey, pix);#ifdef DEBUG_XP_STYLE printf("+++Adding pixmap to cache, size(%d, %d), wasAlphaSwapped(%d), wasAlphaFixed(%d), name(%s)\n", w, h, wasAlphaSwapped, wasAlphaFixed, qPrintable(pixmapCacheKey));#endif } // Add to theme part cache if (!isCached) { memset(&data, 0, sizeof(data)); data.dataValid = true; data.partIsTransparent = partIsTransparent; data.alphaType = alphaType; data.hasAlphaChannel = hasAlpha; data.hasAnyData = stateHasData; data.wasAlphaSwapped = wasAlphaSwapped; data.hadInvalidAlpha = wasAlphaFixed; alphaCache.insert(key, data); }}// ------------------------------------------------------------------------------------------------/*! \class QWindowsXPStyle \brief The QWindowsXPStyle class provides a Microsoft WindowsXP-like look and feel. \ingroup appearance \warning This style is only available on the Windows XP platform because it makes use of Windows XP's style engine. Most of the functions are documented in the base classes QWindowsStyle, QCommonStyle, and QStyle, but the QWindowsXPStyle overloads of drawComplexControl(), drawControl(), drawControlMask(), drawPrimitive(), subControlRect(), and sizeFromContents(), are documented here. \img qwindowsxpstyle.png \sa QMacStyle, QWindowsStyle, QPlastiqueStyle, QCDEStyle, QMotifStyle*//*! Constructs a QWindowsStyle*/QWindowsXPStyle::QWindowsXPStyle() : QWindowsStyle(*new QWindowsXPStylePrivate){}/*! Destroys the style.*/QWindowsXPStyle::~QWindowsXPStyle(){}/*! \reimp */void QWindowsXPStyle::unpolish(QApplication *app){ QWindowsStyle::unpolish(app);}/*! \reimp */void QWindowsXPStyle::polish(QApplication *app){ QWindowsStyle::polish(app); if (!QWindowsXPStylePrivate::useXP()) return;}/*! \reimp */void QWindowsXPStyle::polish(QWidget *widget){ QWindowsStyle::polish(widget); if (!QWindowsXPStylePrivate::useXP()) return; if (qobject_cast<QAbstractButton*>(widget) || qobject_cast<QToolButton*>(widget) || qobject_cast<QTabBar*>(widget) || qobject_cast<QComboBox*>(widget) || qobject_cast<QScrollBar*>(widget) || qobject_cast<QSlider*>(widget) || qobject_cast<QHeaderView*>(widget) || qobject_cast<QAbstractSpinBox*>(widget) || qobject_cast<QSpinBox*>(widget) || widget->inherits("QWorkspaceChild") || widget->inherits("Q3TitleBar")) widget->setAttribute(Qt::WA_Hover);#ifndef QT_NO_RUBBERBAND if (qobject_cast<QRubberBand*>(widget)) { widget->setWindowOpacity(0.6); }#endif if (qobject_cast<QStackedWidget*>(widget) && qobject_cast<QTabWidget*>(widget->parent())) widget->parentWidget()->setAttribute(Qt::WA_ContentsPropagated); Q_D(QWindowsXPStyle); if (!d->hasInitColors) { // Get text color for groupbox labels COLORREF cref; XPThemeData theme(0, 0, "BUTTON", 0, 0); pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_NORMAL, TMT_TEXTCOLOR, &cref); d->groupBoxTextColor = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); pGetThemeColor(theme.handle(), BP_GROUPBOX, GBS_DISABLED, TMT_TEXTCOLOR, &cref); d->groupBoxTextColorDisabled = qRgb(GetRValue(cref), GetGValue(cref), GetBValue(cref)); // Where does this color come from? //pGetThemeColor(theme.handle(), TKP_TICS, TSS_NORMAL, TMT_COLOR, &cref); d->sliderTickColor = qRgb(165, 162, 148); d->hasInitColors = true; }}/*! \reimp */void QWindowsXPStyle::polish(QPalette &pal){ QWindowsStyle::polish(pal); pal.setBrush(QPalette::AlternateBase, pal.base().color().dark(110));}/*! \reimp */void QWindowsXPStyle::unpolish(QWidget *widget){#ifndef QT_NO_RUBBERBAND if (qobject_cast<QRubberBand*>(widget)) { widget->setWindowOpacity(1.0); }#endif Q_D(QWindowsXPStyle); // Unpolish of widgets is the first thing that // happens when a theme changes, or the theme // engine is turned off. So we detect it here. bool oldState = QWindowsXPStylePrivate::useXP(); bool newState = QWindowsXPStylePrivate::useXP(true); if ((oldState != newState) && newState) { d->cleanup(true); d->init(true); } else { // Cleanup handle map, if just changing style, // or turning it on. In both cases the values // already in the map might be old (other style). d->cleanupHandleMap(); } QWindowsStyle::unpolish(widget);}/*! \reimp */QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option, const QWidget *widget) const{ if (!QWindowsXPStylePrivate::useXP()) { return QWindowsStyle::subElementRect(sr, option, widget); } QRect rect(option->rect); switch(sr) { case SE_TabWidgetTabContents: if (qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) { rect = QWindowsStyle::subElementRect(sr, option, widget); if (sr == SE_TabWidgetTabContents) rect.adjust(0, 0, -2, -2); } break; case SE_TabWidgetTabBar: { rect = QWindowsStyle::subElementRect(sr, option, widget); const QStyleOptionTabWidgetFrame *twfOption = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option); if (twfOption && twfOption->direction == Qt::RightToLeft && (twfOption->shape == QTabBar::RoundedNorth || twfOption->shape == QTabBar::RoundedSouth)) { QStyleOptionTab otherOption; otherOption.shape = (twfOption->shape == QTabBar::RoundedNorth ? QTabBar::RoundedEast : QTabBar::RoundedSouth); int overlap = pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget); int borderThickness = pixelMetric(PM_DefaultFrameWidth, option, widget); rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0); } break;} case SE_PushButtonContents: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { MARGINS borderSize; if (widget) { HTHEME theme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), L"Button"); if (theme) { int stateId; if (!(option->state & State_Enabled)) stateId = PBS_DISABLED; else if (option->state & State_Sunken) stateId = PBS_PRESSED; else if (option->state & State_MouseOver) stateId = PBS_HOT; else if (btn->features & QStyleOptionButton::DefaultButton) stateId = PBS_DEFAULTED; else stateId = PBS_NORMAL; int border = pixelMetric(PM_DefaultFrameWidth, btn, widget); rect = option->rect.adjusted(border, border, -border, -border); int result = pGetThemeMargins(theme, NULL, BP_PUSHBUTTON, stateId, TMT_CONTENTMARGINS, NULL, &borderSize); if (result == S_OK) { rect.adjust(borderSize.cxLeftWidth, borderSize.cyTopHeight, -borderSize.cxRightWidth, -borderSize.cyBottomHeight); rect = visualRect(option->direction, option->rect, rect); } } } } break; default: rect = QWindowsStyle::subElementRect(sr, option, widget); } return rect;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -