📄 sxskinregionmanager.pas
字号:
unit SXSkinRegionManager;
////////////////////////////////////////////////////////////////////////////////
// SXSkinComponents: Skinnable Visual Controls for Delphi and C++Builder //
//----------------------------------------------------------------------------//
// Version: 1.2.1 //
// Author: Alexey Sadovnikov //
// Web Site: http://www.saarixx.info/sxskincomponents/ //
// E-Mail: sxskincomponents@saarixx.info //
//----------------------------------------------------------------------------//
// LICENSE: //
// 1. You may freely distribute this file. //
// 2. You may not make any changes to this file. //
// 3. The only person who may change this file is Alexey Sadovnikov. //
// 4. You may use this file in your freeware projects. //
// 5. If you want to use this file in your shareware or commercial project, //
// you should purchase a project license or a personal license of //
// SXSkinComponents: http://saarixx.info/sxskincomponents/en/purchase.htm //
// 6. You may freely use, distribute and modify skins for SXSkinComponents. //
// 7. You may create skins for SXSkinComponents. //
//----------------------------------------------------------------------------//
// Copyright (C) 2006-2007, Alexey Sadovnikov. All Rights Reserved. //
////////////////////////////////////////////////////////////////////////////////
interface
{$I Compilers.inc}
uses Windows, Classes, SXSkinLibrary, GR32, SysUtils, GR32_Resamplers,
SXZipUtils, SXMathEval;
type
TSXSkinPreloadedRegion=class
public
Resized:Boolean;
Width:Integer;
Height:Integer;
FilePath:String;
Color:TColor32;
ColorMask:TColor32;
Region:HRGN;
SkinLibrary:TSXSkinLibrary;
destructor Destroy; override;
end;
TSXSkinPreloadedRegionList=class
protected
FItem:TList;
function Get(const Index:Integer):TSXSkinPreloadedRegion;
procedure Put(const Index:Integer;const Item:TSXSkinPreloadedRegion);
function GetCount:Integer;
public
procedure Add(Region:TSXSkinPreloadedRegion);
function GetRegionIndex(Region:TSXSkinPreloadedRegion):Integer;
procedure Delete(const Index:Integer);
procedure Clear;
constructor Create;
destructor Destroy; override;
property Item[const Index:Integer]:TSXSkinPreloadedRegion read Get write Put; default;
property Count:Integer read GetCount;
end;
function GetPreloadedRegion(SkinLibrary:TSXSkinLibrary;Tile:Boolean;
const FilePath,ZipFilePath:String;Resized:Boolean;Width:Integer;
Height:Integer;SaveResized:Boolean;Color,ColorMask:TColor32):HRGN;
procedure DeletePreloadedRegions(SkinLibrary:TSXSkinCustomLibrary);
function EvaluateRegion(const Region,SkinFilePath:String;ZipFilePath:String;
Width,Height:Integer;SkinLibrary:TSXSkinLibrary;SaveResized:Boolean;
AOnGetVariable:TSXOnGetVariable=nil):HRGN;
var PreloadedRegions:TSXSkinPreloadedRegionList;
implementation
uses Math, jpeg, SXPNGUtils, SXSkinUtils;
function CompareRegions(Region1,Region2:TSXSkinPreloadedRegion):Integer;
begin
Result:=CompareValue(Integer(Region1.SkinLibrary),Integer(Region2.SkinLibrary));
if Result=0 then
Result:=CompareStr(Region1.FilePath,Region2.FilePath) else exit;
if Result=0 then
Result:=CompareValue(Region1.Color,Region2.Color) else exit;
if Result=0 then
Result:=CompareValue(Region1.ColorMask,Region2.ColorMask) else exit;
if Result=0 then
Result:=CompareValue(Ord(Region1.Resized),Ord(Region2.Resized)) else exit;
if Result<>0 then exit;
if Region1.Resized then
begin
Result:=CompareValue(Ord(Region1.Width),Ord(Region2.Width));
if Result=0 then
Result:=CompareValue(Ord(Region1.Height),Ord(Region2.Height)) else exit;
end;
end;
function CreateRgnFromBitmap(B:TBitmap32;Color,ColorMask:TColor32):HRGN;
var A,C,StartX:Integer;
RgnData:PRgnData;
Size,Count:Integer;
MS:TMemoryStream;
P:PColor32;
R:TRect;
begin
Result:=0;
if B.Empty then exit;
MS:=TMemoryStream.Create;
try
P:=@B.Bits[0];
StartX:=-1;
for A:=0 to B.Height-1 do
begin
for C:=0 to B.Width-1 do
begin
if P^ and ColorMask<>Color then
begin
if StartX<0 then
StartX:=C;
end else
begin
if StartX>=0 then
begin
R:=Rect(StartX,A,C,A+1);
MS.Write(R,sizeof(R));
StartX:=-1;
end;
end;
Inc(P);
end;
if StartX>=0 then
begin
R:=Rect(StartX,A,B.Width,A+1);
MS.Write(R,sizeof(R));
StartX:=-1;
end;
end;
Count:=MS.Size div sizeof(TRect);
Size:=sizeof(TRgnDataHeader)+MS.Size;
GetMem(RgnData,Size);
FillChar(RgnData^,Size,0);
RgnData^.rdh.dwSize:=sizeof(TRgnDataHeader);
RgnData^.rdh.iType:=RDH_RECTANGLES;
RgnData^.rdh.nCount:=Count;
RgnData^.rdh.nRgnSize:=0;
RgnData^.rdh.rcBound:=Rect(0,0,B.Width,B.Height);
Move(MS.Memory^,RgnData^.Buffer,MS.Size);
Result:=ExtCreateRegion(nil,Size,RgnData^);
FreeMem(RgnData);
finally
MS.Free;
end;
end;
{ TSXSkinPreloadedRegion }
destructor TSXSkinPreloadedRegion.Destroy;
begin
if Region<>0 then
DeleteObject(Region);
inherited;
end;
{ TSXSkinPreloadedRegionList }
function TSXSkinPreloadedRegionList.Get(const Index:Integer):TSXSkinPreloadedRegion;
begin
Result:=TSXSkinPreloadedRegion(FItem[Index]);
end;
procedure TSXSkinPreloadedRegionList.Put(const Index:Integer;const Item:TSXSkinPreloadedRegion);
begin
FItem[Index]:=Item;
end;
function TSXSkinPreloadedRegionList.GetCount:Integer;
begin
Result:=FItem.Count;
end;
procedure TSXSkinPreloadedRegionList.Add(Region:TSXSkinPreloadedRegion);
var L,H,A,C:Integer;
begin
L:=0;
H:=Count-1;
while L<=H do
begin
A:=(L+H) shr 1;
C:=CompareRegions(Region,Item[A]);
if C<0 then L:=A+1 else
begin
H:=A-1;
if C=0 then L:=A;
end;
end;
FItem.Insert(L,Region);
end;
function TSXSkinPreloadedRegionList.GetRegionIndex(Region:TSXSkinPreloadedRegion):Integer;
var A,C:Integer;
L,H:Integer;
begin
L:=0;
H:=Count-1;
while L<=H do
begin
A:=(L+H) shr 1;
C:=CompareRegions(Region,Item[A]);
if C<0 then L:=A+1 else
begin
H:=A-1;
if C=0 then L:=A;
end;
end;
if (L>=0) and (L<Count) and (CompareRegions(Region,Item[L])=0) then
Result:=L else Result:=-1;
end;
procedure TSXSkinPreloadedRegionList.Delete(const Index:Integer);
begin
Item[Index].Free;
FItem.Delete(Index);
end;
procedure TSXSkinPreloadedRegionList.Clear;
var A:Integer;
begin
for A:=0 to Count-1 do
Item[A].Free;
FItem.Clear;
end;
constructor TSXSkinPreloadedRegionList.Create;
begin
inherited Create;
FItem:=TList.Create;
end;
destructor TSXSkinPreloadedRegionList.Destroy;
begin
Clear;
FItem.Free;
inherited Destroy;
end;
////////////////////////////////////////////////////////////////////////////
function TileRegion(Rgn:HRGN;Width,Height,NewWidth,NewHeight:Integer):HRGN;
var X,Y,XN,YN:Integer;
TmpRgn:HRGN;
begin
Result:=CreateRectRgn(0,0,0,0);
if (Width=0) or (Height=0) then exit;
XN:=NewWidth div Width;
YN:=NewHeight div Height;
if NewWidth mod Width=0 then Dec(XN);
if NewHeight mod Height=0 then Dec(YN);
for X:=0 to XN do
begin
if X<>0 then
OffsetRgn(Rgn,Width,0);
CombineRgn(Result,Result,Rgn,RGN_OR);
end;
if XN>0 then
OffsetRgn(Rgn,-XN*Width,0);
if YN>0 then
begin
TmpRgn:=CreateRectRgn(0,0,0,0);
CombineRgn(TmpRgn,Result,0,RGN_COPY);
for Y:=1 to YN do
begin
OffsetRgn(TmpRgn,0,Height);
CombineRgn(Result,Result,TmpRgn,RGN_OR);
end;
DeleteObject(TmpRgn);
end;
TmpRgn:=CreateRectRgn(0,0,NewWidth,NewHeight);
CombineRgn(Result,Result,TmpRgn,RGN_AND);
DeleteObject(TmpRgn);
end;
function GetPreloadedRegion(SkinLibrary:TSXSkinLibrary;Tile:Boolean;
const FilePath,ZipFilePath:String;Resized:Boolean;Width:Integer;
Height:Integer;SaveResized:Boolean;Color,ColorMask:TColor32):HRGN;
type TRectArray=array of TRect;
var A,B,W,H:Integer;
R:TSXSkinPreloadedRegion;
B2:TBitmap32;
BmpWidth:Integer;
BmpHeight:Integer;
JPG:TJpegImage;
PNG:TPNGObject;
MS:TMemoryStream;
ImageType:TSXSkinStyleImageType;
ZipFile:TZipFile;
RgnData:PRgnData;
XForm:TXForm;
begin
R:=TSXSkinPreloadedRegion.Create;
R.SkinLibrary:=SkinLibrary;
R.FilePath:=FilePath;
R.Color:=Color;
R.ColorMask:=ColorMask;
R.Resized:=Resized;
R.Width:=Width;
R.Height:=Height;
A:=PreloadedRegions.GetRegionIndex(R);
if A>=0 then
begin
Result:=PreloadedRegions[A].Region;
R.Free;
exit;
end;
if Resized then
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -