📄 qwindowsxpstyle.cpp
字号:
#ifdef DEBUG_XP_STYLE void dumpNativeDIB(int w, int h); void showProperties(XPThemeData &themeData);#endif static QAtomic ref; static bool use_xp; static QWidget *limboWidget; static QPixmap *tabbody; QHash<ThemeMapKey, ThemeMapData> alphaCache; HDC bufferDC; HBITMAP bufferBitmap; HBITMAP nullBitmap; uchar *bufferPixels; int bufferW, bufferH;};// Theme data helper ------------------------------------------------------------------------------/* \internal Returns true if the themedata is valid for use.*/bool XPThemeData::isValid(){ return QWindowsXPStylePrivate::useXP() && name.size() && handle();}/* \internal Returns the theme engine handle to the specific class. If the handle hasn't been opened before, it opens the data, and adds it to a static map, for caching.*/HTHEME XPThemeData::handle(){ if (!QWindowsXPStylePrivate::useXP()) return 0; if (!htheme && QWindowsXPStylePrivate::handleMap) htheme = QWindowsXPStylePrivate::handleMap->operator[](name); if (!htheme) { htheme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), (TCHAR*)name.utf16()); if (htheme) { if (!QWindowsXPStylePrivate::handleMap) QWindowsXPStylePrivate::handleMap = new QMap<QString, HTHEME>; QWindowsXPStylePrivate::handleMap->operator[](name) = htheme; } } return htheme;}/* \internal Converts a QRect to the native RECT structure.*/RECT XPThemeData::toRECT(const QRect &qr){ RECT r; r.left = qr.x(); r.right = qr.x() + qr.width(); r.top = qr.y(); r.bottom = qr.y() + qr.height(); return r;}/* \internal Returns the native region of a part, if the part is considered transparent. The region is scaled to the parts size (rect).*/HRGN XPThemeData::mask(){ if (!pIsThemeBackgroundPartiallyTransparent(handle(), partId, stateId)) return 0; HRGN hrgn; HDC dc = painter == 0 ? 0 : painter->paintEngine()->getDC(); RECT nativeRect = toRECT(rect); pGetThemeBackgroundRegion(handle(), dc, partId, stateId, &nativeRect, &hrgn); if (dc) painter->paintEngine()->releaseDC(dc); return hrgn;}// QWindowsXPStylePrivate -------------------------------------------------------------------------// Static initializationsQWidget *QWindowsXPStylePrivate::limboWidget = 0;QPixmap *QWindowsXPStylePrivate::tabbody = 0;QMap<QString,HTHEME> *QWindowsXPStylePrivate::handleMap = 0;bool QWindowsXPStylePrivate::use_xp = false;QAtomic QWindowsXPStylePrivate::ref = QAtomic(-1); // -1 based refcounting/* \internal Checks if the theme engine can/should be used, or if we should fall back to Windows style.*/bool QWindowsXPStylePrivate::useXP(bool update){ if (!update) return use_xp; return (use_xp = resolveSymbols() && pIsThemeActive() && (pIsAppThemed() || !QApplication::instance()));}/* \internal Handles refcounting, and queries the theme engine for usage.*/void QWindowsXPStylePrivate::init(bool force){ if (ref.ref() && !force) return; if (!force) // -1 based atomic refcounting ref.ref(); useXP(true);}/* \internal Cleans up all static data.*/void QWindowsXPStylePrivate::cleanup(bool force){ if(bufferBitmap) DeleteObject(bufferBitmap); bufferBitmap = 0; if(bufferDC) DeleteDC(bufferDC); bufferDC = 0; if (ref.deref() && !force) return; if (!force) // -1 based atomic refcounting ref.deref(); use_xp = false; cleanupHandleMap(); delete limboWidget; delete tabbody; limboWidget = 0; tabbody = 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 example the user changes the theme style.*/void QWindowsXPStylePrivate::cleanupHandleMap(){ if (!handleMap) return; QMap<QString, HTHEME>::Iterator it; for (it = handleMap->begin(); it != handleMap->end(); ++it) pCloseThemeData(it.value()); delete handleMap; handleMap = 0;}/*! \internal This function will always return a valid window handle, and might create a limbo widget to do so. We often need a window handle to for example open theme data, so this function ensures that we get one.*/HWND QWindowsXPStylePrivate::winId(const QWidget *widget){ if (widget) return widget->winId(); if (!limboWidget) { limboWidget = new QWidget(0); limboWidget->setObjectName(QLatin1String("xp_limbo_widget")); } return limboWidget->winId();}/*! \internal Returns the pointer to a tab widgets body pixmap, scaled to the 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 *){ if (!tabbody) { SIZE sz; XPThemeData theme(0, 0, "TAB", TABP_BODY); pGetThemePartSize(theme.handle(), qt_win_display_dc(), TABP_BODY, 0, 0, TS_TRUE, &sz); tabbody = new QPixmap(sz.cx, QApplication::desktop()->screenGeometry().height()); QPainter painter(tabbody); theme.rect = QRect(0, 0, sz.cx, sz.cy); 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); } return tabbody;}/*! \internal Returns true if all the necessary theme engine symbols were resolved.*/bool QWindowsXPStylePrivate::resolveSymbols(){ static bool tried = false; if (!tried) { tried = true; QLibrary themeLib("uxtheme"); pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); if (pIsAppThemed) { pIsThemeActive = (PtrIsThemeActive )themeLib.resolve("IsThemeActive"); pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); pOpenThemeData = (PtrOpenThemeData )themeLib.resolve("OpenThemeData"); pCloseThemeData = (PtrCloseThemeData )themeLib.resolve("CloseThemeData"); pDrawThemeBackground = (PtrDrawThemeBackground )themeLib.resolve("DrawThemeBackground"); pDrawThemeBackgroundEx = (PtrDrawThemeBackgroundEx )themeLib.resolve("DrawThemeBackgroundEx"); pGetCurrentThemeName = (PtrGetCurrentThemeName )themeLib.resolve("GetCurrentThemeName"); pGetThemeBool = (PtrGetThemeBool )themeLib.resolve("GetThemeBool"); pGetThemeColor = (PtrGetThemeColor )themeLib.resolve("GetThemeColor"); pGetThemeEnumValue = (PtrGetThemeEnumValue )themeLib.resolve("GetThemeEnumValue"); pGetThemeFilename = (PtrGetThemeFilename )themeLib.resolve("GetThemeFilename"); pGetThemeFont = (PtrGetThemeFont )themeLib.resolve("GetThemeFont"); pGetThemeInt = (PtrGetThemeInt )themeLib.resolve("GetThemeInt"); pGetThemeIntList = (PtrGetThemeIntList )themeLib.resolve("GetThemeIntList"); pGetThemeMargins = (PtrGetThemeMargins )themeLib.resolve("GetThemeMargins"); pGetThemeMetric = (PtrGetThemeMetric )themeLib.resolve("GetThemeMetric"); pGetThemePartSize = (PtrGetThemePartSize )themeLib.resolve("GetThemePartSize"); pGetThemePosition = (PtrGetThemePosition )themeLib.resolve("GetThemePosition"); pGetThemePropertyOrigin = (PtrGetThemePropertyOrigin)themeLib.resolve("GetThemePropertyOrigin"); pGetThemeRect = (PtrGetThemeRect )themeLib.resolve("GetThemeRect"); pGetThemeString = (PtrGetThemeString )themeLib.resolve("GetThemeString"); pGetThemeBackgroundRegion = (PtrGetThemeBackgroundRegion )themeLib.resolve("GetThemeBackgroundRegion"); pGetThemeDocumentationProperty = (PtrGetThemeDocumentationProperty )themeLib.resolve("GetThemeDocumentationProperty"); pIsThemeBackgroundPartiallyTransparent = (PtrIsThemeBackgroundPartiallyTransparent)themeLib.resolve("IsThemeBackgroundPartiallyTransparent"); } } return pIsAppThemed != 0;}/*! \internal Returns a native buffer (DIB section) of at least the size of ( \a x , \a y ). The buffer has a 32 bit depth, to not lose the alpha values on proper alpha-pixmaps.*/HBITMAP QWindowsXPStylePrivate::buffer(int w, int h){ // If we already have a HBITMAP which is of adequate size, just return that if (bufferBitmap) { if (bufferW >= w && bufferH >= h) return bufferBitmap; // Not big enough, discard the old one if (bufferDC && nullBitmap) SelectObject(bufferDC, nullBitmap); DeleteObject(bufferBitmap); bufferBitmap = 0; } w = qMax(bufferW, w); h = qMax(bufferH, h); if (!bufferDC) bufferDC = CreateCompatibleDC(qt_win_display_dc()); // Define the header BITMAPINFO bmi; memset(&bmi, 0, sizeof(bmi)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = w; bmi.bmiHeader.biHeight = -h; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; // Create the pixmap bufferPixels = 0; bufferBitmap = CreateDIBSection(bufferDC, &bmi, DIB_RGB_COLORS, (void **) &bufferPixels, 0, 0); GdiFlush(); nullBitmap = (HBITMAP)SelectObject(bufferDC, bufferBitmap); if (!bufferBitmap) { qErrnoWarning("QWindowsXPStylePrivate::buffer(w,h), failed to create dibsection"); bufferW = 0; bufferH = 0; return 0; } if (!bufferPixels) { qErrnoWarning("QWindowsXPStylePrivate::buffer(w,h), did not allocate pixel data"); bufferW = 0; bufferH = 0; return 0; } bufferW = w; bufferH = h;#ifdef DEBUG_XP_STYLE qDebug("Creating new dib section (%d, %d)", w, h);#endif return bufferBitmap;}/*! \internal Returns true if the part contains any transparency at all. This does not indicate what kind of transparency we're dealing with. It can be - Alpha transparency - Masked transparency*/bool QWindowsXPStylePrivate::isTransparent(XPThemeData &themeData){ return pIsThemeBackgroundPartiallyTransparent(themeData.handle(), themeData.partId, themeData.stateId);}/*! \internal Returns a QRegion of the region of the part*/QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData){ HRGN hRgn = 0; RECT rect = themeData.toRECT(themeData.rect); if (!SUCCEEDED(pGetThemeBackgroundRegion(themeData.handle(), bufferHDC(), themeData.partId, themeData.stateId, &rect, &hRgn))) return QRegion(); QRegion rgn = QRegion(0,0,1,1); CombineRgn(rgn.handle(), hRgn, 0, RGN_COPY); DeleteObject(hRgn); return rgn;}/*! \internal Sets the parts region on a window.*/void QWindowsXPStylePrivate::setTransparency(QWidget *widget, XPThemeData &themeData){ HRGN hrgn = themeData.mask(); if (hrgn) SetWindowRgn(winId(widget), hrgn, true);}/*! \internal Returns true if the native doublebuffer contains a pixel which has a non-0xFF alpha value. Should only be use when its guaranteed that data painted into the buffer wasn't a proper alpha pixmap.*/bool QWindowsXPStylePrivate::hasAnyData(const QRect &rect){ const int startX = rect.left(); const int startY = rect.top();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -