📄 sxskinform.pas
字号:
unit SXSkinForm;
////////////////////////////////////////////////////////////////////////////////
// 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 GR32_Image, GR32, Windows, Graphics, Classes, Messages, Forms, StdCtrls,
ExtCtrls, SysUtils, Controls, SXSkinLibrary, Types;
{$IFNDEF COMPILER_7_UP}
{$EXTERNALSYM WM_NCMOUSELEAVE}
const WM_NCMOUSELEAVE = $02A2;
{$ENDIF}
type
TSXSkinCustomForm=class(TComponent)
private
FSkinLibrary:TSXSkinLibrary;
FSkinStyle:String;
FForm:TForm;
FCaptionHeight:Integer;
FFormActive:Boolean;
FCustomCaptionHeight:Integer;
FIconRect:TRect;
FTextRect:TRect;
FCloseRect:TRect;
FMaximizeRect:TRect;
FMinimizeRect:TRect;
FHelpRect:TRect;
FCloseOver:Boolean;
FMaximizeOver:Boolean;
FMinimizeOver:Boolean;
FHelpOver:Boolean;
FCloseDown:Boolean;
FMaximizeDown:Boolean;
FMinimizeDown:Boolean;
FHelpDown:Boolean;
OldWindowProc:TWndMethod;
TmpWidth:Integer;
TmpHeight:Integer;
ResizeTopLeftRgn:HRGN;
ResizeTopRightRgn:HRGN;
ResizeBottomLeftRgn:HRGN;
ResizeBottomRightRgn:HRGN;
ResizeLeftRgn:HRGN;
ResizeRightRgn:HRGN;
ResizeTopRgn:HRGN;
ResizeBottomRgn:HRGN;
CaptionRgn:HRGN;
LastLeft,LastTop:Integer;
FTextBitmap:TBitmap32;
FIconStyle:String;
FUseTFormIcon:Boolean;
//
CEID_Caption:Integer;
CEID_LeftFrame:Integer;
CEID_RightFrame:Integer;
CEID_BottomFrame:Integer;
CEID_Icon:Integer;
CEID_Close:Integer;
CEID_Maximize:Integer;
CEID_Minimize:Integer;
CEID_Help:Integer;
CEID_Restore:Integer;
function HasUnusualSkinStyle:Boolean;
function HasUnusualIconStyle:Boolean;
procedure SetSkinStyle(const Value:String);
procedure SetSkinLibrary(Value:TSXSkinLibrary);
procedure SetUseTFormIcon(Value:Boolean);
procedure SetCustomCaptionHeight(Value:Integer);
procedure NewWndProc(var Message:TMessage);
procedure GetCurrentFState(var FState:TSXSkinFormStateParam;
PSkinFilePath:PString=nil;PZipFilePath:PString=nil);
function OnGetVariable(const VarName:String;var Error:Boolean):Single;
procedure CalcResizeRegions;
function HitTest(X,Y:Integer):Integer;
procedure ProcessNCMouseMove;
protected
procedure Notification(AComponent:TComponent;Operation:TOperation); override;
public
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
procedure DrawCaptionAndBorder(Rgn:HRGN);
procedure DrawCaptionToRect(Bitmap:TBitmap32;Rect:TRect);
procedure ResetMaskRegion;
procedure CalcCaptionElementsRects;
procedure SkinChanged;
property CustomCaptionHeight:Integer read FCustomCaptionHeight write SetCustomCaptionHeight default 0;
property IconStyle:String read FIconStyle write FIconStyle stored HasUnusualIconStyle;
property SkinLibrary:TSXSkinLibrary read FSkinLibrary write SetSkinLibrary;
property SkinStyle:String read FSkinStyle write SetSkinStyle stored HasUnusualSkinStyle;
property UseTFormIcon:Boolean read FUseTFormIcon write SetUseTFormIcon default True;
end;
TSXSkinForm=class(TSXSkinCustomForm)
published
property CustomCaptionHeight;
property IconStyle;
property SkinLibrary;
property SkinStyle;
property UseTFormIcon;
end;
implementation
uses SXSkinRegionManager, SXMathEval, SXBitmap32Utils, SXSkinUtils;
type
TSXForm=class(TForm);
{ TSXSkinCustomForm }
function TSXSkinCustomForm.HasUnusualIconStyle:Boolean;
begin
Result:=SkinStyle<>'_Selective_StdIcon';
end;
function TSXSkinCustomForm.HasUnusualSkinStyle:Boolean;
begin
Result:=SkinStyle<>'_Form';
end;
procedure TSXSkinCustomForm.SetSkinLibrary(Value:TSXSkinLibrary);
begin
if FSkinLibrary<>Value then
begin
if FSkinLibrary<>nil then
begin
FSkinLibrary.RemoveFreeNotification(Self);
FSkinLibrary.RemoveSkinComponent(Self);
end;
FSkinLibrary:=Value;
if FSkinLibrary<>nil then
begin
FSkinLibrary.FreeNotification(Self);
FSkinLibrary.AddSkinComponent(Self);
end;
if not (csDestroying in ComponentState) then
SkinChanged;
end;
end;
procedure TSXSkinCustomForm.SetSkinStyle(const Value:String);
begin
if FSkinStyle<>Value then
begin
FSkinStyle:=Value;
SkinChanged;
end;
end;
procedure TSXSkinCustomForm.SetUseTFormIcon(Value:Boolean);
begin
if FUseTFormIcon<>Value then
begin
FUseTFormIcon:=Value;
if FForm<>nil then
SendMessage(FForm.Handle,WM_NCPAINT,0,0);
end;
end;
procedure TSXSkinCustomForm.SetCustomCaptionHeight(Value:Integer);
begin
if FCustomCaptionHeight<>Value then
begin
FCustomCaptionHeight:=Value;
if FForm<>nil then
begin
SetWindowPos(FForm.Handle, 0, 0, 0, 0, 0, SWP_FRAMECHANGED or SWP_NOMOVE or
SWP_NOREPOSITION or SWP_NOSIZE or SWP_NOACTIVATE);
FForm.Invalidate;
end;
end;
end;
procedure TSXSkinCustomForm.Notification(AComponent:TComponent;Operation:TOperation);
begin
inherited Notification(AComponent,Operation);
if Operation=opRemove then
begin
if AComponent=FSkinLibrary then
FSkinLibrary:=nil;
end;
end;
procedure TSXSkinCustomForm.SkinChanged;
begin
ResetMaskRegion;
CalcResizeRegions;
CalcCaptionElementsRects;
if FForm<>nil then
SendMessage(FForm.Handle,WM_NCPAINT,0,0);
end;
procedure TSXSkinCustomForm.GetCurrentFState(var FState:TSXSkinFormStateParam;
PSkinFilePath:PString=nil;PZipFilePath:PString=nil);
var A:Integer;
Style:TSXSkinFormStyle;
begin
Finalize(FState);
FillChar(FState,sizeof(FState),0);
if (SkinLibrary<>nil) and SkinLibrary.CanBeUsed and (FForm<>nil) then
begin
A:=SkinLibrary.Styles.GetIndexByName(SkinStyle);
if (A>=0) and (SkinLibrary.Styles[A] is TSXSkinFormStyle) then
begin
Style:=TSXSkinFormStyle(SkinLibrary.Styles[A]);
if PSkinFilePath<>nil then
PSkinFilePath^:=Style.SkinFilePath;
if PZipFilePath<>nil then
PZipFilePath^:=Style.ZipFilePath;
Style.GetCurrentFState(FState,FForm.WindowState=wsMaximized,
FForm.WindowState=wsMinimized,FFormActive);
end;
end;
end;
procedure TSXSkinCustomForm.DrawCaptionToRect(Bitmap:TBitmap32;Rect:TRect);
var FState:TSXSkinFormStateParam;
TextRect,RR:TRect;
W,H:Integer;
Flags:Cardinal;
procedure DrawStyleToRect(CElementID:Integer;const StyleName:String;X,Y,Width,Height:Integer);
var A:Integer;
GStyle:TSXSkinGeneralStyle;
ARect:TRect;
Rgn:HRGN;
begin
if (Width<=0) or (Height<=0) then exit;
if StyleName<>'' then
begin
A:=SkinLibrary.Styles.GetGStyleIndex(StyleName,Width,Height);
if A>=0 then
begin
GStyle:=TSXSkinGeneralStyle(SkinLibrary.Styles[A]);
ARect:=Types.Rect(0,0,Width,Height);
OffsetRect(ARect,Rect.Left,Rect.Top);
Rgn:=CreateRectRgnIndirect(ARect);
GStyle.DrawToBitmap(FForm,CElementID,Bitmap,X+Rect.Left,Y+Rect.Top,Width,
Height,ARect,Rgn,SkinLibrary);
DeleteObject(Rgn);
end;
end;
end;
procedure DrawTextToBitmap(Bitmap:TBitmap32);
begin
SetDefaultFontData(FState.TextFont,FForm.Font);
Bitmap.Font.Name:=FState.TextFont.FontName;
Bitmap.Font.Size:=FState.TextFont.FontSize;
Bitmap.Font.Style:=FState.TextFont.FontStyle;
if FState.TextFont.HasShadow then
begin
OffsetRect(TextRect,1,1);
if FState.TextFont.SmoothLevel=0 then
begin
if FState.TextFont.ShadowColor shr 24=$FF then
begin
Bitmap.Font.Color:=WinColor(FState.TextFont.ShadowColor);
Bitmap.Textout(TextRect,Flags,FForm.Caption);
end else DrawAlphaText(Bitmap,FForm.Caption,TextRect,Flags,FState.TextFont.ShadowColor);
end else
DrawSmoothText(Bitmap,FForm.Caption,TextRect,Flags,FState.TextFont.SmoothLevel,FState.TextFont.ShadowColor);
OffsetRect(TextRect,-1,-1);
end;
if FState.TextFont.SmoothLevel=0 then
begin
if FState.TextFont.FontColor shr 24=$FF then
begin
Bitmap.Font.Color:=WinColor(FState.TextFont.FontColor);
Bitmap.Textout(TextRect,Flags,FForm.Caption);
end else DrawAlphaText(Bitmap,FForm.Caption,TextRect,Flags,FState.TextFont.FontColor);
end else DrawSmoothText(Bitmap,FForm.Caption,TextRect,Flags,FState.TextFont.SmoothLevel,FState.TextFont.FontColor);
end;
procedure DrawButton(CElementID:Integer;const ButtonRect:TRect;
ButtonOver,ButtonDown:Boolean;const ButtonStyle:String;ButtonEnabled:Boolean);
var A:Integer;
BStyle:TSXSkinButtonStyle;
BState:TSXSkinButtonStateParam;
begin
if not IsRectEmpty(ButtonRect) and (ButtonStyle<>'') then
begin
A:=SkinLibrary.Styles.GetIndexByName(ButtonStyle);
if (A>=0) and (SkinLibrary.Styles[A] is TSXSkinButtonStyle) then
begin
BStyle:=TSXSkinButtonStyle(SkinLibrary.Styles[A]);
BStyle.GetCurrentBState(BState,False,ButtonEnabled,ButtonOver,
ButtonOver and ButtonDown,ButtonDown);
if BState.Style<>'' then
DrawStyleToRect(CElementID,BState.Style,ButtonRect.Left,ButtonRect.Top,
ButtonRect.Right-ButtonRect.Left,ButtonRect.Bottom-ButtonRect.Top);
end;
end;
end;
begin
if (SkinLibrary<>nil) and SkinLibrary.CanBeUsed and (FForm<>nil) then
begin
GetCurrentFState(FState);
if FState.CaptionStyle<>'' then
DrawStyleToRect(CEID_Caption,FState.CaptionStyle,0,0,FForm.Width,FCaptionHeight);
if not IsRectEmpty(FIconRect) then
begin
if FUseTFormIcon then
begin
H:=FForm.Icon.Handle;
if H=0 then H:=Application.Icon.Handle;
DrawIconEx(Bitmap.Handle,FIconRect.Left+Rect.Left,FIconRect.Top+Rect.Top,H,
FIconRect.Right-FIconRect.Left,FIconRect.Bottom-FIconRect.Top,
0,0,DI_NORMAL);
end else DrawStyleToRect(CEID_Icon,FIconStyle,FIconRect.Left,FIconRect.Top,
FIconRect.Right-FIconRect.Left,FIconRect.Bottom-FIconRect.Top);
end;
//
DrawButton(CEID_Close,FCloseRect,FCloseOver,FCloseDown,FState.CloseButton,biSystemMenu in FForm.BorderIcons);
if FForm.WindowState=wsMaximized then
DrawButton(CEID_Restore,FMaximizeRect,FMaximizeOver,FMaximizeDown,FState.RestoreButton,biMaximize in FForm.BorderIcons) else
DrawButton(CEID_Maximize,FMaximizeRect,FMaximizeOver,FMaximizeDown,FState.MaximizeButton,biMaximize in FForm.BorderIcons);
DrawButton(CEID_Minimize,FMinimizeRect,FMinimizeOver,FMinimizeDown,FState.MinimizeButton,biMinimize in FForm.BorderIcons);
DrawButton(CEID_Help,FHelpRect,FHelpOver,FHelpDown,FState.HelpButton,True);
//
if FForm.Caption<>'' then
begin
Flags:=DT_NOPREFIX or DT_NOCLIP or DT_TOP or DT_VCENTER or DT_SINGLELINE or
DT_MODIFYSTRING or DT_END_ELLIPSIS;
case FState.TextAlignment of
taLeftJustify: Flags:=Flags or DT_LEFT;
taRightJustify: Flags:=Flags or DT_RIGHT;
taCenter: Flags:=Flags or DT_CENTER;
end;
TextRect:=FTextRect;
if FState.TextFont.DoPrepaint and (FState.TextFont.SmoothLevel>0) and (FTextBitmap=nil) then
begin
FTextBitmap:=TBitmap32.Create;
FTextBitmap.DrawMode:=dmBlend;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -