qwindowsxpstyle.cpp
来自「qt-x11-free-3.0.3.tar.gz minigui图形界面工具」· C++ 代码 · 共 1,876 行 · 第 1/4 页
CPP
1,876 行
#include "qwindowsxpstyle.h"#if !defined (Q_WS_WIN)#error "This style can only be compiled on Windows XP"#endif#ifndef QT_NO_STYLE_WINDOWSXP#include "qmenubar.h"#include <qpainter.h>#include <qpushbutton.h>#include <qtoolbutton.h>#include <qtabbar.h>#include <qheader.h>#include <qspinbox.h>#include <qgroupbox.h>#include <qapplication.h>#include <qcursor.h>#include <qscrollbar.h>#include <qslider.h>#include <qcheckbox.h>#include <qradiobutton.h>#include <qcombobox.h>#include <qlistbox.h>#include <private/qtitlebar_p.h>#include <qlistview.h>#include <qcleanuphandler.h>#include <qbitmap.h>#include <qt_windows.h>#include <uxtheme.h>#include <tmschema.h>static ulong ref = 0;static bool use_xp = FALSE;static bool init_xp = FALSE;class QWindowsXPStylePrivate{public: QWindowsXPStylePrivate() : hotWidget( 0 ), hotTab( 0 ), hotSpot( -1, -1 ) { init(); } ~QWindowsXPStylePrivate() { cleanup(); } void init() { if ( qWinVersion() != Qt::WV_XP ) { use_xp = FALSE; init_xp = TRUE; } if ( !init_xp ) { init_xp = TRUE; use_xp = IsThemeActive() && IsAppThemed(); } if ( use_xp ) ref++; } void cleanup() { init_xp = FALSE; if ( use_xp ) { if ( !--ref ) { use_xp = FALSE; delete limboWidget; limboWidget = 0; delete tabbody; tabbody = 0; } } } static bool getThemeResult( HRESULT res ) { if ( res == S_OK ) return TRUE; return FALSE; } static HWND winId( const QWidget *widget ) { if ( widget ) return widget->winId(); if ( currentWidget ) return currentWidget->winId(); if ( !limboWidget ) limboWidget = new QWidget( 0, "xp_limbo_widget" ); return limboWidget->winId(); } const QPixmap *tabBody( QWidget *widget ); // hot-widget stuff const QWidget *hotWidget; static const QWidget *currentWidget; QTab *hotTab; QRect hotHeader; QPoint hotSpot;private: static QWidget *limboWidget; static QPixmap *tabbody;};const QWidget *QWindowsXPStylePrivate::currentWidget = 0;QWidget *QWindowsXPStylePrivate::limboWidget = 0;QPixmap *QWindowsXPStylePrivate::tabbody = 0;struct XPThemeData{ XPThemeData( const QWidget *w = 0, QPainter *p = 0, LPCWSTR theme = 0, int part = 0, int state = 0, const QRect &r = QRect() ) : widget( w ), painter( p ), name( theme ),partId( part ), stateId( state ), rec( r ), htheme( 0 ) { } ~XPThemeData() { if ( htheme ) CloseThemeData( htheme ); } HTHEME handle() { if ( !use_xp ) return NULL; if ( !htheme ) htheme = OpenThemeData( QWindowsXPStylePrivate::winId( widget ), name ); return htheme; } bool isValid() { return use_xp && !!name && handle(); } RECT rect() { RECT r; r.left = rec.x(); r.right = rec.x() + rec.width(); r.top = rec.y(); r.bottom = rec.y() + rec.height(); return r; } void operator=( const XPThemeData &orig ) { if ( htheme ) CloseThemeData( htheme ); name = orig.name; partId = orig.partId; stateId = orig.stateId; rec = orig.rec; htheme = orig.htheme; } HRGN mask() { if ( IsThemeBackgroundPartiallyTransparent( handle(), partId, stateId ) ) { HRGN hrgn; GetThemeBackgroundRegion( handle(), painter ? painter->handle() : 0, partId, stateId, &rect(), &hrgn ); return hrgn; } return 0; } void setTransparency() { HRGN hrgn = mask(); if ( hrgn ) SetWindowRgn( QWindowsXPStylePrivate::winId( widget ), hrgn, FALSE ); } void drawBackground( int pId = 0, int sId = 0 ) { if ( pId ) partId = pId; if ( sId ) stateId = sId; if ( name && !wcscmp( name, L"TAB" ) && ( partId == TABP_TABITEMLEFTEDGE || partId == TABP_TABITEMRIGHTEDGE || partId == TABP_TABITEM ) ) { QRect oldrec = rec; rec = QRect( 0, 0, rec.width(), rec.height() ); QPixmap pm( rec.size() ); QPainter p( &pm ); p.eraseRect( 0, 0, rec.width(), rec.height() ); DrawThemeBackground( handle(), p.handle(), partId, stateId, &rect(), 0 ); rec = oldrec; painter->drawPixmap( rec.x(), rec.y(), pm ); } else { ulong res = DrawThemeBackground( handle(), painter->handle(), partId, stateId, &rect(), 0 ); } } int partId; int stateId; QRect rec; private: const QWidget *widget; QPainter *painter; LPCWSTR name; HTHEME htheme; bool workAround;};const QPixmap *QWindowsXPStylePrivate::tabBody( QWidget *widget ){ if ( !tabbody ) { tabbody = new QPixmap( 1, 1 ); QPainter painter( tabbody ); XPThemeData theme( widget, &painter, L"TAB", TABP_BODY, 0 ); SIZE sz; GetThemePartSize( theme.handle(), painter.handle(), TABP_BODY, 0, 0, TS_TRUE, &sz ); painter.end(); tabbody->resize( sz.cx, sz.cy ); painter.begin( tabbody ); theme.rec = QRect( 0, 0, sz.cx, sz.cy ); theme.drawBackground(); painter.end(); } return tabbody;}QWindowsXPStyle::QWindowsXPStyle(): QWindowsStyle(){ d = new QWindowsXPStylePrivate;}QWindowsXPStyle::~QWindowsXPStyle(){ delete d;}void QWindowsXPStyle::unPolish( QApplication *app ){ d->cleanup(); QWindowsStyle::unPolish( app );}void QWindowsXPStyle::polish( QApplication *app ){ QWindowsStyle::polish( app ); d->init();}void QWindowsXPStyle::polish( QWidget *widget ){ QWindowsStyle::polish( widget ); if ( !use_xp ) return; if ( widget->inherits( "QButton" ) ) { widget->installEventFilter( this ); widget->setBackgroundOrigin( QWidget::ParentOrigin ); } else if ( widget->inherits( "QTabBar" ) ) { widget->installEventFilter( this ); widget->setMouseTracking( TRUE ); connect( widget, SIGNAL(selected(int)), this, SLOT(activeTabChanged()) ); } else if ( widget->inherits( "QHeader" ) ) { widget->installEventFilter( this ); widget->setMouseTracking( TRUE ); } else if ( widget->inherits( "QComboBox" ) ) { widget->installEventFilter( this ); widget->setMouseTracking( TRUE ); } else if ( widget->inherits( "QSpinWidget" ) ) { widget->installEventFilter( this ); widget->setMouseTracking( TRUE ); } else if ( widget->inherits( "QScrollBar" ) ) { widget->installEventFilter( this ); widget->setMouseTracking( TRUE ); } else if ( widget->inherits( "QTitleBar" ) ) { widget->installEventFilter( this ); widget->setMouseTracking( TRUE ); } else if ( widget->inherits( "QWorkspaceChild" ) ) { widget->installEventFilter( this ); } else if ( widget->inherits( "QSlider" ) ) { widget->installEventFilter( this ); widget->setMouseTracking( TRUE ); } else if ( widget->inherits( "QWidgetStack" ) && widget->parentWidget() && widget->parentWidget()->inherits( "QTabWidget" ) ) { widget->setPaletteBackgroundPixmap( *d->tabBody( widget ) ); } else if ( widget->inherits( "QMenuBar" ) ) { QPalette pal = widget->palette(); XPThemeData theme( widget, 0, L"MENUBAR", 0, 0 ); if ( theme.isValid() ) { COLORREF cref; GetThemeColor( theme.handle(), 0, 0, TMT_MENUBAR, &cref ); QColor menubar( qRgb(GetRValue(cref),GetGValue(cref),GetBValue(cref)) ); pal.setColor( QColorGroup::Button, menubar ); } else { QPalette apal = QApplication::palette(); pal.setColor( QPalette::Active, QColorGroup::Button, apal.color( QPalette::Active, QColorGroup::Button ) ); pal.setColor( QPalette::Inactive, QColorGroup::Button, apal.color( QPalette::Inactive, QColorGroup::Button ) ); pal.setColor( QPalette::Disabled, QColorGroup::Button, apal.color( QPalette::Disabled, QColorGroup::Button ) ); } widget->setPalette( pal ); } updateRegion( widget );}void QWindowsXPStyle::unPolish( QWidget *widget ){ widget->removeEventFilter( this ); if ( widget->inherits( "QTitleBar" ) && !widget->inherits( "QDockWindowTitleBar" ) ) { SetWindowRgn( widget->winId(), 0, TRUE ); if ( widget->isMinimized() ) { SetWindowRgn( widget->parentWidget()->winId(), 0, TRUE ); } } else if ( widget->inherits( "QWorkspaceChild" ) ) { SetWindowRgn( widget->winId(), 0, TRUE ); } else if ( widget->inherits( "QWidgetStack" ) && widget->parentWidget() && widget->parentWidget()->inherits( "QTabWidget" ) ) { widget->setPaletteBackgroundPixmap( QPixmap() ); } else if ( widget->inherits( "QTabBar" ) ) { disconnect( widget, SIGNAL(selected(int)), this, SLOT(activeTabChanged()) ); } QWindowsStyle::unPolish( widget );}void QWindowsXPStyle::updateRegion( QWidget *widget ){ if ( !use_xp ) return; if ( widget->inherits( "QTitleBar" ) && !widget->inherits( "QDockWindowTitleBar" ) ) { if ( widget->isMinimized() ) { XPThemeData theme( widget, 0, L"WINDOW", WP_MINCAPTION, CS_ACTIVE, widget->rect() ); theme.setTransparency(); XPThemeData theme2( widget->parentWidget(), 0, L"WINDOW", WP_MINCAPTION, CS_ACTIVE, widget->rect() ); theme2.setTransparency(); } else { int partId = WP_CAPTION; if ( widget->inherits( "QDockWindowTitleBar" ) ) partId = WP_SMALLCAPTION; XPThemeData theme( widget, 0, L"WINDOW", partId, CS_ACTIVE, widget->rect() ); theme.setTransparency(); } } else if ( widget->inherits( "QWorkspaceChild" ) ) { XPThemeData theme( widget, 0, L"WINDOW", WP_CAPTION, CS_ACTIVE, widget->rect() ); theme.setTransparency(); theme.rec = widget->parentWidget()->rect(); RECT r = theme.rect(); InvalidateRect( widget->parentWidget()->winId(), &r, TRUE ); }}void QWindowsXPStyle::drawPrimitive( PrimitiveElement op, QPainter *p, const QRect &r, const QColorGroup &cg, SFlags flags, const QStyleOption &opt ) const{ if ( !use_xp ) { QWindowsStyle::drawPrimitive( op, p, r, cg, flags, opt ); return; } LPCWSTR name = 0; int partId = 0; int stateId = 0; QRect rect = r; switch ( op ) { case PE_ButtonCommand: case PE_ButtonBevel: name = L"BUTTON"; partId = BP_PUSHBUTTON; if ( !flags & Style_Enabled ) stateId = PBS_DISABLED; else if ( flags & Style_Down || flags & Style_Sunken ) stateId = PBS_PRESSED; else if ( flags & Style_MouseOver ) stateId = PBS_HOT; else if ( flags & Style_ButtonDefault ) stateId = PBS_DEFAULTED; else stateId = PBS_NORMAL; break; case PE_ButtonTool: name = L"TOOLBAR"; partId = TP_BUTTON; if ( !flags & Style_Enabled ) stateId = TS_DISABLED; else if ( flags & Style_Down || flags & Style_Sunken ) stateId = TS_PRESSED; else if ( flags & Style_MouseOver ) stateId = flags & Style_On ? TS_HOTCHECKED : TS_HOT; else if ( flags & Style_On ) stateId = TS_CHECKED; else stateId = TS_NORMAL; break; case PE_ButtonDropDown: name = L"TOOLBAR"; partId = TP_SPLITBUTTONDROPDOWN; if ( !flags & Style_Enabled ) stateId = TS_DISABLED; else if ( flags & Style_Down || flags & Style_Sunken ) stateId = TS_PRESSED; else if ( flags & Style_MouseOver ) stateId = flags & Style_On ? TS_HOTCHECKED : TS_HOT; else if ( flags & Style_On ) stateId = TS_CHECKED; else stateId = TS_NORMAL; break; case PE_Indicator: name = L"BUTTON"; partId = BP_CHECKBOX; if ( !(flags & Style_Enabled) ) stateId = CBS_UNCHECKEDDISABLED; else if ( flags & Style_Down ) stateId = CBS_UNCHECKEDPRESSED; else if ( flags & Style_MouseOver ) stateId = CBS_UNCHECKEDHOT; else stateId = CBS_UNCHECKEDNORMAL; if ( flags & Style_On ) stateId += CBS_CHECKEDNORMAL-1; else if ( flags & Style_NoChange ) stateId += CBS_MIXEDNORMAL-1; break; case PE_IndicatorMask: p->fillRect( r, color1 ); return; case PE_ExclusiveIndicator: name = L"BUTTON"; partId = BP_RADIOBUTTON; if ( !(flags & Style_Enabled) ) stateId = RBS_UNCHECKEDDISABLED; else if ( flags & Style_Down ) stateId = RBS_UNCHECKEDPRESSED; else if ( flags & Style_MouseOver ) stateId = RBS_UNCHECKEDHOT; else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?