DevExpress Skin 正常情况下只能对他自己的组件和系统组件添加皮肤效果,而第三方组件无法使用。如果程序里面使用了非DevExpress的组件,切换皮肤时会导致非DevExpress 组件与DevExpress组件界面不搭配。DevExpress VCL Skin Adapter 就是来解决这个问题的。
cxLookAndFeels 单元有一个RootLookAndFeel全局变量,替换此全局变量的OnChanged方法为自定义的方法,然后在自定义的OnChanged中通知其他组件程序皮肤已经切换,其他组件做对应的皮肤调整。
uDxSkinAdapter.pas 单元源码
unit uDxSkinAdapter;
interface
uses System.SysUtils,System.Classes,Winapi.Messages,Winapi.Windows,System.SyncObjs,cxLookAndFeels,dxSkinsForm;
type
IcxLookAndFeelHandler = interface //第三方组件继承此接口
['{8CB3F0DB-3B89-4D03-ADEA-A11735736205}']
procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues); //当皮肤切换时调用此函数,组件做对应皮肤调整
end;
TDxSkinAdapter=class(TObject)
private
FLock:TCriticalSection;
FList:TList;
FSavLookAndFeelChanged: TcxLookAndFeelChangedEvent;
procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues);
procedure SetLookAndFeelChangedHandler(Attach: Boolean);
public
constructor Create();
destructor Destroy; override;
procedure AddHandler(Component: TComponent);//添加需要通知皮肤切换事件的组件
procedure RemoveHandler(Component: TComponent);//删除组件的皮肤切换通知
end;
var
DxSkinAdapter:TDxSkinAdapter;//全局变量
implementation
procedure TDxSkinAdapter.SetLookAndFeelChangedHandler(Attach: Boolean);
var
CrtLookAndFeel: TcxLookAndFeel;
IsAttached: Boolean;
begin
CrtLookAndFeel := RootLookAndFeel();
if CrtLookAndFeel <> nil then
begin
IsAttached :=
(TMethod(CrtLookAndFeel.OnChanged).Data = Self) and
(TMethod(CrtLookAndFeel.OnChanged).Code = @TDxSkinAdapter.LookAndFeelChanged);
if Attach and not IsAttached then
begin
FSavLookAndFeelChanged := CrtLookAndFeel.OnChanged;
CrtLookAndFeel.OnChanged := LookAndFeelChanged;
end
else if not Attach and IsAttached then
begin
CrtLookAndFeel.OnChanged := FSavLookAndFeelChanged;
FSavLookAndFeelChanged := nil;
end;
end;
end;
procedure TDxSkinAdapter.LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues);
var
i:Integer;
Component: TComponent;
AIntf:IcxLookAndFeelHandler;
begin
FLock.Enter;
try
for i := 0 to FList.Count-1 do
begin
Component:=TComponent(FList[i]);
if (Component<>nil) and (Component.GetInterface(IcxLookAndFeelHandler,AIntf)) then
begin
AIntf.LookAndFeelChanged(Sender,AChangedValues);
end;
end;
finally
FLock.Leave;
end;
end;
procedure TDxSkinAdapter.AddHandler(Component: TComponent);
var
AIntf:IcxLookAndFeelHandler;
begin
FLock.Enter;
try
if (Component<>nil) and (Component.GetInterface(IcxLookAndFeelHandler,AIntf)) then FList.Add(Component);
finally
FLock.Leave;
end;
end;
procedure TDxSkinAdapter.RemoveHandler(Component: TComponent);
var
Index:Integer;
begin
FLock.Enter;
try
Index:=FList.IndexOf(Component);
if Index>=0 then FList.Delete(Index);
finally
FLock.Leave;
end;
end;
constructor TDxSkinAdapter.Create();
begin
FList:=TList.Create;
FLock:=TCriticalSection.Create;
SetLookAndFeelChangedHandler(True);
end;
destructor TDxSkinAdapter.Destroy;
begin
SetLookAndFeelChangedHandler(False);
FreeAndNil(FLock);
FreeAndNil(FList);
end;
initialization
DxSkinAdapter := TDxSkinAdapter.Create();//全局初始化
finalization
FreeAndNil(DxSkinAdapter);
end.
使用方法
unit uChart;
interface
uses System.Classes,Vcl.Controls,VCLTee.Chart,uDxSkinAdapter,cxLookAndFeels;
type
TAdvChart = class(TChart,IcxLookAndFeelHandler) //第三方组件继承接口
private
procedure ChangeLookAndFeel();
public
procedure LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues);//接口函数,皮肤切换通知
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
end;
implementation
procedure TAdvChart.ChangeLookAndFeel();
begin
Gradient.StartColor := RootLookAndFeel.Painter.DefaultContentColor;
Gradient.EndColor := RootLookAndFeel.Painter.DefaultContentColor;
end;
procedure TAdvChart.LookAndFeelChanged(Sender: TcxLookAndFeel; AChangedValues: TcxLookAndFeelValues);
begin
ChangeLookAndFeel;
end;
constructor TAdvChart.Create(AOwner: TComponent);
begin
inherited;
Gradient.Visible:=True;
View3DWalls:=False;
View3D:=False;
BevelOuter:=bvNone;
ChangeLookAndFeel;
DxSkinAdapter.AddHandler(Self);//此组件需要获取皮肤切换事件
end;
destructor TAdvChart.Destroy;
begin
DxSkinAdapter.RemoveHandler(Self);//删除皮肤切换通知事件
inherited;
end;
效果:
顺便贴上 TMS Component Skin 皮肤切换在第三方组件上的应用,详细介绍见http://www.tmssoftware.com/site/atbdev3.asp
unit AdvChart;
interface
uses
Classes,TeeProcs, TeEngine, Chart,DBChart, Series, AdvStyleIF,Controls,Graphics;
type
TAdvChart = class(TChart, ITMSStyle)
public
procedure SetComponentStyle(AStyle: TTMSStyle);
end;
TDBAdvChart = class(TDBChart, ITMSStyle)
public
procedure SetComponentStyle(AStyle: TTMSStyle);
end;
implementation
procedure TAdvChart.SetComponentStyle(AStyle: TTMSStyle);
begin
Gradient.Visible:=True;
View3DWalls:=False;
View3D:=False;
BevelOuter:=bvNone;
case AStyle of
tsOffice2003Blue:
begin
Gradient.StartColor := $00FDEADA;
Gradient.EndColor := $00E4AE88;
end;
tsOffice2003Silver:
begin
Gradient.StartColor := $00F7F3F3;
Gradient.EndColor := $00E6D8D8;
end;
tsOffice2003Olive:
begin
Gradient.StartColor := $00CFF0EA;
Gradient.EndColor := $008CC0B1;
end;
tsOffice2003Classic:
begin
Gradient.StartColor := clWhite;
Gradient.EndColor := $00C9D1D5;
end;
tsOffice2007Luna:
begin
Gradient.StartColor := $FAF1E9;
Gradient.EndColor := $EDD8C7;
end;
tsOffice2007Obsidian:
begin
Gradient.StartColor := $CFC6C1;
Gradient.EndColor := $C5BBB4;
end;
tsWindowsXP:
begin
Gradient.StartColor := clBtnFace;
Gradient.EndColor := clBtnFace;
end;
tsWhidbey:
begin
Gradient.StartColor := clWhite;
Gradient.EndColor := $00D9E9EC;
end;
tsCustom: ;
tsOffice2007Silver:
begin
Gradient.StartColor := $F6F1EE;
Gradient.EndColor := $E7DCD5;
end;
tsWindowsVista:
begin
Gradient.StartColor := $FDF8F1;
Gradient.EndColor := $FCEFD5;
end;
tsWindows7:
begin
Gradient.StartColor := $FCEBDC;
Gradient.EndColor := $FCDBC1;
end;
tsTerminal:
begin
Gradient.StartColor := clBtnFace;
Gradient.EndColor := clBtnFace;
end;
tsOffice2010Blue:
begin
Gradient.StartColor := $FDF6EF;
Gradient.EndColor := $F0DAC7;
end;
tsOffice2010Silver:
begin
Gradient.StartColor := $FFFFFF;
Gradient.EndColor := $EDE5E0;
end;
tsOffice2010Black:
begin
Gradient.StartColor := $BFBFBF;
Gradient.EndColor := $919191;
end;
end;
end;
procedure TDBAdvChart.SetComponentStyle(AStyle: TTMSStyle);
begin
Gradient.Visible:=True;
View3DWalls:=False;
View3D:=False;
BevelOuter:=bvNone;
case AStyle of
tsOffice2003Blue:
begin
Gradient.StartColor := $00FDEADA;
Gradient.EndColor := $00E4AE88;
end;
tsOffice2003Silver:
begin
Gradient.StartColor := $00F7F3F3;
Gradient.EndColor := $00E6D8D8;
end;
tsOffice2003Olive:
begin
Gradient.StartColor := $00CFF0EA;
Gradient.EndColor := $008CC0B1;
end;
tsOffice2003Classic:
begin
Gradient.StartColor := clWhite;
Gradient.EndColor := $00C9D1D5;
end;
tsOffice2007Luna:
begin
Gradient.StartColor := $FAF1E9;
Gradient.EndColor := $EDD8C7;
end;
tsOffice2007Obsidian:
begin
Gradient.StartColor := $CFC6C1;
Gradient.EndColor := $C5BBB4;
end;
tsWindowsXP:
begin
Gradient.StartColor := clBtnFace;
Gradient.EndColor := clBtnFace;
end;
tsWhidbey:
begin
Gradient.StartColor := clWhite;
Gradient.EndColor := $00D9E9EC;
end;
tsCustom: ;
tsOffice2007Silver:
begin
Gradient.StartColor := $F6F1EE;
Gradient.EndColor := $E7DCD5;
end;
tsWindowsVista:
begin
Gradient.StartColor := $FDF8F1;
Gradient.EndColor := $FCEFD5;
end;
tsWindows7:
begin
Gradient.StartColor := $FCEBDC;
Gradient.EndColor := $FCDBC1;
end;
tsTerminal:
begin
Gradient.StartColor := clBtnFace;
Gradient.EndColor := clBtnFace;
end;
tsOffice2010Blue:
begin
Gradient.StartColor := $FDF6EF;
Gradient.EndColor := $F0DAC7;
end;
tsOffice2010Silver:
begin
Gradient.StartColor := $FFFFFF;
Gradient.EndColor := $EDE5E0;
end;
tsOffice2010Black:
begin
Gradient.StartColor := $BFBFBF;
Gradient.EndColor := $919191;
end;
end;
end;
end.