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 + -
显示快捷键?