📄 dxbarskin.pas
字号:
{*******************************************************************}
{ }
{ Developer Express Visual Component Library }
{ ExpressBars components }
{ }
{ Copyright (c) 1998-2008 Developer Express Inc. }
{ ALL RIGHTS RESERVED }
{ }
{ The entire contents of this file is protected by U.S. and }
{ International Copyright Laws. Unauthorized reproduction, }
{ reverse-engineering, and distribution of all or any portion of }
{ the code contained in this file is strictly prohibited and may }
{ result in severe civil and criminal penalties and will be }
{ prosecuted to the maximum extent possible under the law. }
{ }
{ RESTRICTIONS }
{ }
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
{ LICENSED TO DISTRIBUTE THE EXPRESSBARS AND ALL ACCOMPANYING VCL }
{ CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
{ }
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
{ }
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
{ ADDITIONAL RESTRICTIONS. }
{ }
{*******************************************************************}
unit dxBarSkin;
{$I cxVer.inc}
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ImgList, ExtCtrls, cxGraphics, dxGDIPlusAPI;
type
TcxSkinRectType = (spt1x1, spt3x1, spt1x3, spt3x3);
TdxCustomBarSkin = class;
{ TdxSkinnedRect }
TdxSkin3x3Part = (
sp3x3TopLeft, sp3x3Top, sp3x3TopRight,
sp3x3Left, sp3x3Center, sp3x3Right,
sp3x3BottomLeft, sp3x3Bottom, sp3x3BottomRight
);
{ TdxSkinnedRect }
TdxSkinnedRect = class
private
FAlphaValue: Byte;
FCalculatedSize: TSize;
FDrawPartSizes: array[TdxSkin3x3Part] of TSize;
FFixedPartSize: TRect;
FGPImage: GpBitmap;
FGPCacheBitmap: GpBitmap;
FID: Integer;
FInterpolationMode: Integer;
FLastSize: TSize;
FMinSize: TSize;
FName: string;
FOpaque: Boolean;
FOwner: TdxCustomBarSkin;
FPartBounds: array[TdxSkin3x3Part] of TRect;
FTextOffset: TRect;
procedure CalculatePartBounds(const ARect: TRect);
procedure CheckCachedImage;
procedure CheckCalculate(AWidth, AHeight: Integer);
procedure UpdateCacheImage;
procedure UpdateSizes;
protected
procedure Calculate(AWidth, AHeight: Integer); virtual;
procedure Clear; virtual;
procedure DefaultDraw(DC: HDC; const R: TRect); virtual;
procedure DoDraw(DC: HDC; const R: TRect); virtual;
property CalculatedSize: TSize read FCalculatedSize;
public
constructor Create(AOpaque: Boolean = False);
destructor Destroy; override;
procedure Draw(DC: HDC; const R: TRect; AlphaValue: Byte = 255);
function GetBitmap(const AWidth, AHeight: Integer; AUseAlphaChannel: Boolean = False): TBitmap;
function GetTextBounds(const R: TRect): TRect; virtual;
procedure LoadFromBitmap(ABitmap: GpBitmap; const ARect, AFixedPartSize: TRect);
procedure LoadFromFile(const AFileName: string; const AFixedPartSize: TRect); overload;
procedure LoadFromFile(const AFileName: string; const ARect, AFixedPartSize: TRect); overload;
property AlphaValue: Byte read FAlphaValue write FAlphaValue default 255;
property ID: Integer read FID write FID;
property InterpolationMode: Integer read FInterpolationMode write FInterpolationMode
default InterpolationModeDefault;
property MinSize: TSize read FMinSize write FMinSize;
property Name: string read FName write FName;
property Opaque: Boolean read FOpaque write FOpaque;
property Owner: TdxCustomBarSkin read FOwner;
property TextOffset: TRect read FTextOffset write FTextOffset;
end;
{ TdxCustomBarSkin }
TdxCustomBarSkin = class(TList)
private
FName: string;
function GetPart(Index: Integer): TdxSkinnedRect;
protected
function IsPersistent: Boolean; virtual;
public
constructor Create(const AName: string);
procedure Clear; override;
function Add(ASkinnedRect: TdxSkinnedRect): Integer;
function AddPart1x1(ABitmap: GpBitmap; const R: TRect; AID: Integer;
const AName: string = ''; AInterpolationMode: Integer = InterpolationModeDefault): Integer;
function AddPart1x3(ABitmap: GpBitmap; const R: TRect; ATop, ABottom, AID: Integer;
const AName: string = ''; AInterpolationMode: Integer = InterpolationModeDefault): Integer;
function AddPart3x3(ABitmap: GpBitmap; const R, AFixedSize: TRect;
AID: Integer; const AName: string = ''; AInterpolationMode: Integer = InterpolationModeDefault): Integer;
function PartByName(const AName: string): TdxSkinnedRect;
function PartByID(const AID: Integer): TdxSkinnedRect;
property Name: string read FName write FName;
property Parts[Index: Integer]: TdxSkinnedRect read GetPart; default;
end;
{ TcxSkinManager }
TdxBarSkinManager = class(TPersistent)
private
FList: TList;
function GetSkin(Index: Integer): TdxCustomBarSkin;
function GetSkinCount: Integer;
protected
function CanDeleteSkin(ASkin: TdxCustomBarSkin): Boolean;
procedure Changed; virtual;
public
constructor Create;
destructor Destroy; override;
function AddSkin(ASkin: TdxCustomBarSkin): Integer;
function RemoveSkin(ASkin: TdxCustomBarSkin): Boolean;
function SkinByName(const AName: string): TdxCustomBarSkin;
property SkinCount: Integer read GetSkinCount;
property Skins[Index: Integer]: TdxCustomBarSkin read GetSkin; default;
end;
function SkinManager: TdxBarSkinManager;
function GetImageFromStream(AStream: TStream): GPImage;
implementation
uses
{$IFDEF DELPHI6}
Types,
{$ENDIF}
cxGeometry, dxOffice11, cxControls, dxBar, cxDWMApi, ActiveX;
var
FSkinManager: TdxBarSkinManager;
function SkinManager: TdxBarSkinManager;
begin
if FSkinManager = nil then
FSkinManager := TdxBarSkinManager.Create;
Result := FSkinManager;
end;
function GetImageFromStream(AStream: TStream): GPImage;
var
Data: HGlobal;
DataPtr: Pointer;
AccessStream: IStream;
begin
Result := nil;
if not CheckGdiPlus then Exit;
Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, AStream.Size);
try
DataPtr := GlobalLock(Data);
try
AStream.Read(DataPtr^, AStream.Size);
GdipCheck(CreateStreamOnHGlobal(Data, False, AccessStream) = s_OK);
GdipCheck(GdipCreateBitmapFromStream(AccessStream, Result));
finally
GlobalUnlock(Data);
AccessStream := nil;
end;
finally
GlobalFree(Data);
end;
end;
function dxAlphaBlend(ADestDC: HDC; const ADestRect: TRect; ASrcDC: HDC; const ASrcRect: TRect;
AlphaValue: Byte = 255): Boolean;
begin
if not IsWin95X then
Result := SystemAlphaBlend(ADestDC, ASrcDC, ADestRect, ASrcRect, AlphaValue)
else
begin
Result := True;
cxAlphaBlend(ADestDC, ASrcDC, ADestRect, ASrcRect, False, AlphaValue);
end;
end;
{ TdxSkinnedRect }
constructor TdxSkinnedRect.Create(AOpaque: Boolean = False);
begin
FAlphaValue := 255;
FID := -1;
FOpaque := AOpaque;
FTextOffset := cxRect(8, 8, 8, 8);
FInterpolationMode := InterpolationModeDefault;
end;
destructor TdxSkinnedRect.Destroy;
begin
if FGPImage <> nil then
GdipDisposeImage(FGPImage);
if FGPCacheBitmap <> nil then
GdipDisposeImage(FGPCacheBitmap);
inherited Destroy;
end;
procedure TdxSkinnedRect.Calculate(AWidth, AHeight: Integer);
var
W, H: Integer;
begin
if (FFixedPartSize.Left + FFixedPartSize.Right) >= AWidth then
begin
W := AWidth div 2;
FDrawPartSizes[sp3x3TopLeft].cx := W;
FDrawPartSizes[sp3x3BottomLeft].cx := W;
FDrawPartSizes[sp3x3Left].cx := W;
W := AWidth - W;
FDrawPartSizes[sp3x3TopRight].cx := W;
FDrawPartSizes[sp3x3BottomRight].cx := W;
FDrawPartSizes[sp3x3Right].cx := W;
//don't draw
FDrawPartSizes[sp3x3Center].cx := 0;
FDrawPartSizes[sp3x3Top].cx := 0;
FDrawPartSizes[sp3x3Bottom].cx := 0;
end
else
begin
FDrawPartSizes[sp3x3TopLeft].cx := FFixedPartSize.Left;
FDrawPartSizes[sp3x3Left].cx := FFixedPartSize.Left;
FDrawPartSizes[sp3x3BottomLeft].cx := FFixedPartSize.Left;
FDrawPartSizes[sp3x3TopRight].cx := FFixedPartSize.Right;
FDrawPartSizes[sp3x3Right].cx := FFixedPartSize.Right;
FDrawPartSizes[sp3x3BottomRight].cx := FFixedPartSize.Right;
FDrawPartSizes[sp3x3Center].cx := AWidth - (FFixedPartSize.Right + FFixedPartSize.Left);
FDrawPartSizes[sp3x3Top].cx := FDrawPartSizes[sp3x3Center].cx;
FDrawPartSizes[sp3x3Bottom].cx := FDrawPartSizes[sp3x3Center].cx;
end;
if (FFixedPartSize.Top + FFixedPartSize.Bottom) >= AHeight then
begin
H := AHeight div 2;
FDrawPartSizes[sp3x3TopLeft].cy := H;
FDrawPartSizes[sp3x3TopRight].cy := H;
FDrawPartSizes[sp3x3Top].cy := H;
H := AHeight - H;
FDrawPartSizes[sp3x3BottomLeft].cy := H;
FDrawPartSizes[sp3x3BottomRight].cy := H;
FDrawPartSizes[sp3x3Bottom].cy := H;
//don't draw
FDrawPartSizes[sp3x3Center].cy := 0;
FDrawPartSizes[sp3x3Left].cy := 0;
FDrawPartSizes[sp3x3Right].cy := 0;
end
else
begin
FDrawPartSizes[sp3x3TopLeft].cy := FFixedPartSize.Top;
FDrawPartSizes[sp3x3Top].cy := FFixedPartSize.Top;
FDrawPartSizes[sp3x3TopRight].cy := FFixedPartSize.Top;
FDrawPartSizes[sp3x3BottomLeft].cy := FFixedPartSize.Bottom;
FDrawPartSizes[sp3x3Bottom].cy := FFixedPartSize.Bottom;
FDrawPartSizes[sp3x3BottomRight].cy := FFixedPartSize.Bottom;
FDrawPartSizes[sp3x3Center].cy := AHeight - (FFixedPartSize.Bottom + FFixedPartSize.Top);
FDrawPartSizes[sp3x3Left].cy := FDrawPartSizes[sp3x3Center].cy;
FDrawPartSizes[sp3x3Right].cy := FDrawPartSizes[sp3x3Center].cy;
end;
end;
procedure TdxSkinnedRect.Clear;
begin
FCalculatedSize := cxNullSize;
end;
procedure TdxSkinnedRect.DefaultDraw(DC: HDC; const R: TRect);
begin
FillRectByColor(DC, R, clBtnFace);
end;
procedure TdxSkinnedRect.DoDraw(DC: HDC; const R: TRect);
var
H, OldBitmap: HBITMAP;
BDC: HDC;
begin
CheckCachedImage;
GdipCreateHBITMAPFromBitmap(FGPCacheBitmap, H, 0);
BDC := CreateCompatibleDC(DC);
OldBitmap := SelectObject(BDC, H);
if not FOpaque and not dxAlphaBlend(DC, R, BDC, cxRect(0, 0, CalculatedSize.cx, CalculatedSize.cy), AlphaValue) then
cxBitBlt(DC, BDC, R, cxPoint(0, 0), srccopy);
SelectObject(BDC, OldBitmap);
DeleteDC(BDC);
DeleteObject(H);
end;
procedure TdxSkinnedRect.Draw(DC: HDC; const R: TRect; AlphaValue: Byte = 255);
begin
FAlphaValue := AlphaValue;
if (R.Right - R.Left <= 0) or (R.Bottom - R.Top <= 0) then Exit;
CheckCalculate(R.Right - R.Left, R.Bottom - R.Top);
if RectVisible(DC, R) then
DoDraw(DC, R)
end;
function TdxSkinnedRect.GetBitmap(const AWidth, AHeight: Integer;
AUseAlphaChannel: Boolean = False): TBitmap;
begin
Result := TcxBitmap.CreateSize(AWidth, AHeight);;
if AUseAlphaChannel then
Result.PixelFormat := pf32bit;
Draw(Result.Canvas.Handle, cxRect(0, 0, AWidth, AHeight));
if AUseAlphaChannel then
TcxBitmap(Result).RecoverAlphaChannel(clFuchsia);
end;
function TdxSkinnedRect.GetTextBounds(const R: TRect): TRect;
begin
Result := R;
Inc(Result.Left, FTextOffset.Left);
Inc(Result.Top, FTextOffset.Top);
Dec(Result.Right, FTextOffset.Right);
Dec(Result.Bottom, FTextOffset.Bottom);
end;
procedure TdxSkinnedRect.LoadFromBitmap(ABitmap: GpBitmap;
const ARect, AFixedPartSize: TRect);
var
G: GpGraphics;
begin
Clear;
GdipCheck(GdipCreateBitmapFromScan0(ARect.Right - ARect.Left, ARect.Bottom - ARect.Top,
0, PixelFormat32bppPARGB, nil, FGPImage));
GdipCheck(GdipGetImageGraphicsContext(FGPImage, G));
GdipCheck(GdipSetInterpolationMode(G, InterpolationModeNearestNeighbor));
GdipCheck(GdipSetCompositingMode(G, CompositingModeSourceCopy));
GdipCheck(GdipDrawImageRectRectI(G, ABitmap, 0, 0, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top,
ARect.Left, ARect.Top, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top, UnitPixel, nil, nil, nil));
GdipCheck(GdipDeleteGraphics(G));
FFixedPartSize := AFixedPartSize;
CalculatePartBounds(ARect);
UpdateSizes;
end;
procedure TdxSkinnedRect.LoadFromFile(const AFileName: string;
const AFixedPartSize: TRect);
var
ARect: TRect;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -