ksskinobjects.pas

来自「小区水费管理系统源代码水费收费管理系统 水费收费管理系统」· PAS 代码 · 共 2,327 行 · 第 1/5 页

PAS
2,327
字号
  private
    FFontHot: TFont;
    FFontFocused: TFont;
    FFontPressed: TFont;
    FFontDisabled: TFont;
    procedure SetFontHot(const Value: TFont);
    procedure SetFontDisabled(const Value: TFont);
    procedure SetFontFocused(const Value: TFont);
    procedure SetFontPressed(const Value: TFont);
  protected
    function GetFont: TFont; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    { Assign, Copy }
    procedure Assign(Source: TPersistent); override;
    { Drawing }
    procedure Draw(Canvas: TCanvas); override;
    { Colors }
    procedure ChangeHue(DeltaHue: integer); override;
    { Font }
    procedure SetCharset(CharSet: TFontCharset); override;
  published
    property FontHot: TFont read FFontHot write SetFontHot;
    property FontFocused: TFont read FFontFocused write SetFontFocused;
    property FontPressed: TFont read FFontPressed write SetFontPressed;
    property FontDisabled: TFont read FFontDisabled write SetFontDisabled;
  end;

{ Registration }

var
  RegObjects: TList; { registered class }

procedure RegisterSkinObject(ObjectClass: TSeSkinObjectClass);
function GetSkinObjectClass(ClassName: string): TSeSkinObjectClass;

procedure SaveSkinObject(Stream: TStream; SkinObject: TSeSkinObject);
function LoadSkinObject(Stream: TStream; Owner: TSeSkinObject): TSeSkinObject;

procedure SaveSkinObjectBinary(Stream: TStream; SkinObject: TSeSkinObject);
function LoadSkinObjectBinary(Stream: TStream; Owner: TSeSkinObject): TSeSkinObject;

implementation {===============================================================}

uses KsSkinForms;

procedure RegisterSkinObject(ObjectClass: TSeSkinObjectClass);
begin
  if RegObjects = nil then
    RegObjects := TList.Create;
  if RegObjects <> nil then
    RegObjects.Add(ObjectClass);
end;

function GetSkinObjectClass(ClassName: string): TSeSkinObjectClass;
var
  i: integer;
begin
  for i := 0 to RegObjects.Count-1 do
    if TSeSkinObjectClass(RegObjects[i]).ClassName = ClassName then
    begin
      Result := TSeSkinObjectClass(RegObjects[i]);
      Exit;;
    end;

  Result := nil;
end;

{ I/O Routines }

procedure SaveSkinObject(Stream: TStream; SkinObject: TSeSkinObject);
var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  if SkinObject = nil then Exit;

  BinStream := TMemoryStream.Create;
  try
    StrStream := TStringStream.Create(S);
    try
      BinStream.WriteComponent(SkinObject);
      BinStream.Seek(0, soFromBeginning);
      ObjectBinaryToText(BinStream, StrStream);
      StrStream.Seek(0, soFromBeginning);
      S := StrStream.DataString;
    finally
      StrStream.Free;
    end;
  finally
    BinStream.Free
  end;

  WriteString(Stream, SkinObject.ClassName);
  WriteString(Stream, S);
end;

function LoadSkinObject(Stream: TStream; Owner: TSeSkinObject): TSeSkinObject;
var
  SkinObjectClass: TSeSkinObjectClass;
  S, ClassName: string;
  StrStream:TStringStream;
  BinStream: TMemoryStream;
begin
  Result := nil;

  ClassName := ReadString(Stream);

  { make object }
  SkinObjectClass := GetSkinObjectClass(ClassName);
  if SkinObjectClass <> nil then
    Result := SkinObjectClass.Create(Owner);

  { Load object }
  if Result <> nil then
  begin
    S := ReadString(Stream);
    StrStream := TStringStream.Create(S);
    try
      BinStream := TMemoryStream.Create;
      try
        ObjectTextToBinary(StrStream, BinStream);
        BinStream.Seek(0, soFromBeginning);

        BinStream.ReadComponent(Result);

        { Set Charset }
        Result.SetCharset(DEFAULT_CHARSET);
      finally
        BinStream.Free;
      end;
    finally
      StrStream.Free;
    end;
  end;
end;

procedure SaveSkinObjectBinary(Stream: TStream; SkinObject: TSeSkinObject);
var
  MemStream: TMemoryStream;
  Size: Cardinal;
begin
  WriteString(Stream, SkinObject.ClassName);

  MemStream := TMemoryStream.Create;
  MemStream.WriteComponent(SkinObject);

  Size := MemStream.Size;
  Stream.WriteBuffer(Size, SizeOf(Size));
  Stream.WriteBuffer(MemStream.Memory^, Size);

  MemStream.Free;
end;

function LoadSkinObjectBinary(Stream: TStream; Owner: TSeSkinObject): TSeSkinObject;
var
  SkinObjectClass: TSeSkinObjectClass;
  ClassName: string;
  MemStream: TMemoryStream;
  Size: Cardinal;
begin
  Result := nil;

  ClassName := ReadString(Stream);

  { make object }
  SkinObjectClass := GetSkinObjectClass(ClassName);
  if SkinObjectClass <> nil then
    Result := SkinObjectClass.Create(Owner);

  { Load object }
  if Result <> nil then
  begin
    Stream.ReadBuffer(Size, SizeOf(Size));

    MemStream := TMemoryStream.Create;
    MemStream.SetSize(Size);
    Stream.ReadBuffer(MemStream.Memory^, Size);

    MemStream.ReadComponent(Result);
    MemStream.Free;
    { Set Charset }
    Result.SetCharset(DEFAULT_CHARSET);
  end;
end;

{ TSeSkinObject ===============================================================}

constructor TSeSkinObject.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FEnabled := true;
  FVisible := true;
  FColor := clWhite;
  FFont := TFont.Create;
  FTextAlign := taLeft;
  FMasked := true;
end;

destructor TSeSkinObject.Destroy;
begin
  FFont.Free;
  inherited Destroy;
end;

procedure TSeSkinObject.AfterLoad;
var
  i: integer;
begin
  if Count = 0 then Exit;

  for i := 0 to Count-1 do
    Objects[i].AfterLoad;
end;

{ Protected ===================================================================}

procedure TSeSkinObject.Assign(Source: TPersistent);
var
  i: integer;
  Child: TSeSkinObject;
begin
  if Source is TSeSkinObject then
  begin
    { Assign }
    Name := TSeSkinObject(Source).Name;

    FMasked := TSeSkinObject(Source).FMasked;
    FAlign := TSeSkinObject(Source).FAlign;
    FKind := TSeSkinObject(Source).FKind;
    FAlign := TSeSkinObject(Source).FAlign;
    FBitmaps := TSeSkinObject(Source).FBitmaps;
    FColor := TSeSkinObject(Source).FColor;
    FDrawIfOwner := TSeSkinObject(Source).FDrawIfOwner;
    FFont.Assign(TSeSkinObject(Source).FFont);
    FKind := TSeSkinObject(Source).FKind;
    FTextAlign := TSeSkinObject(Source).FTextAlign;
    FTextEffect := TSeSkinObject(Source).FTextEffect;
    FTextMarginLeft := TSeSkinObject(Source).FTextMarginLeft;
    FTextMarginRight := TSeSkinObject(Source).FTextMarginRight;
    FTextMarginTop := TSeSkinObject(Source).FTextMarginTop;

    FMarginLeft := TSeSkinObject(Source).FMarginLeft;
    FMarginTop := TSeSkinObject(Source).FMarginTop;
    FMarginRight := TSeSkinObject(Source).FMarginRight;
    FMarginBottom := TSeSkinObject(Source).FMarginBottom;

    { Copy Objects }
    for i := 0 to TSeSkinObject(Source).Count - 1 do
    begin
      Child := TSeSkinObject(Source).Objects[i].CreateCopy(Self);
    end;

    { Bounds }
    FLeft := TSeSkinObject(Source).Left;
    FTop := TSeSkinObject(Source).Top;
    FWidth := TSeSkinObject(Source).Width;
    FHeight := TSeSkinObject(Source).Height;
//    BoundsRect := TSeSkinObject(Source).BoundsRect;
  end
  else
    inherited Assign(Source);
end;

function TSeSkinObject.CreateCopy(AOwner: TSeSkinObject): TSeSkinObject;
var
  ClassType: TSeSkinObjectClass;
begin
  ClassType := GetSkinObjectClass(ClassName);
  if ClassType <> nil then
  begin
    Result := ClassType.Create(AOwner);
    Result.Assign(Self);
  end
  else
    Result := nil;
end;

function TSeSkinObject.GetSkinForm: TComponent;
var
  R: Integer;
begin
  Result := nil;

  if FParentControl <> nil then
  begin
    R := SendMessage(FParentControl.Handle, WM_GETSKINFORM, 0, 0);
    if Pointer(R) <> nil then
      Result := TComponent(R);
  end
end;

{ BiDi Mode }

function TSeSkinObject.DrawTextBiDiModeFlags(Flags: Integer): Longint;
begin
  Result := Flags;
  { do not change center alignment }
  if UseRightToLeftAlignment then
    if Result and DT_RIGHT = DT_RIGHT then
      Result := Result and not DT_RIGHT { removing DT_RIGHT, makes it DT_LEFT }
    else if not (Result and DT_CENTER = DT_CENTER) then
      Result := Result or DT_RIGHT;
  Result := Result or DrawTextBiDiModeFlagsReadingOnly;
end;

function TSeSkinObject.DrawTextBiDiModeFlagsReadingOnly: Longint;
begin
  if UseRightToLeftReading then
    Result := DT_RTLREADING
  else
    Result := 0;
end;

function TSeSkinObject.UseRightToLeftAlignment: Boolean;
begin
  Result := SysLocale.MiddleEast and (BiDiMode <> bdLeftToRight);
end;

function TSeSkinObject.UseRightToLeftReading: Boolean;
begin
  Result := SysLocale.MiddleEast and (BiDiMode = bdRightToLeft);
end;

{ Aligning ====================================================================}

procedure TSeSkinObject.Aligning;
var
  i: integer;
  R: TRect;
  Canvas: TCanvas;
begin
  R := BoundsRect;
  { most top & most bottom align }
  for i := 0 to Count-1 do
  begin
    if (Objects[i].Align = saMostTop) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Left, R.Top, R.Right, R.Top+Height);
      Inc(R.Top, Height);
    end;
    if (Objects[i].Align = saMostBottom) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Left, R.Bottom-Height, R.Right, R.Bottom);
      Dec(R.Bottom, Height);
    end;
  end;
  { most left & right align }
  for i := 0 to Count-1 do
  begin
    if (Objects[i].Align = saMostLeft) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Left, R.Top, R.Left+Width, R.Bottom);
      Inc(R.Left, Width);
    end;
    if (Objects[i].Align = saMostRight) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Right-Width, R.Top, R.Right, R.Bottom);
      Dec(R.Right, Width);
    end;
  end;
  { top & bottom align }
  for i := 0 to Count-1 do
  begin
    if (Objects[i].Align = saTop) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Left, R.Top, R.Right, R.Top+Height);
      Inc(R.Top, Height);
    end;
    if (Objects[i].Align = saBottom) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Left, R.Bottom-Height, R.Right, R.Bottom);
      Dec(R.Bottom, Height);
    end;
  end;
  { left & right align }
  for i := 0 to Count-1 do
  begin
    if (Objects[i].Align = saLeft) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Left, R.Top, R.Left+Width, R.Bottom);
      Inc(R.Left, Width);
    end;
    if (Objects[i].Align = saRight) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Right-Width, R.Top, R.Right, R.Bottom);
      Dec(R.Right, Width);
    end;
  end;
  { text align }
  for i := Count-1 Downto 0 do
    if (Objects[i].FVisible) and (Objects[i].Align = saText) then
    with Objects[i] do
    begin
       Canvas := TCanvas.Create;
       Canvas.Handle := GetDC(0);

       Canvas.Font := Font;
       Width := TextMarginLeft + TextMarginRight + TextWidth(Canvas, FText);

       ReleaseDC(0, Canvas.Handle);
       Canvas.Handle := 0;
       Canvas.Free;
    end;
  { center align }
  for i := Count-1 Downto 0 do
    if (Objects[i].Align = saCenter) and (Objects[i].FVisible) then
    with Objects[i] do
    begin
      BoundsRect := Rect(R.Left + (R.Right-R.left-Width) div 2,
        R.Top + (R.Bottom-R.Top-Height) div 2,
        R.Left + (R.Right-R.Left-Width) div 2 + FWidth,
        R.Top + (R.Bottom-R.Top-Height) div 2 + FHeight);
    end;
  { client align }
  for i := 0 to Count-1 do
    if (Objects[i].Align = saClient) and (Objects[i].FVisible) then
      Objects[i].BoundsRect := Rect(R.Left, R.Top, R.Right, R.Bottom);
  { other align }
  for i := 0 to Count-1 do
  begin
    if (Objects[i].Align = saTopRight) and (FOldWidth > 0) then
      Objects[i].FLeft := FWidth - (FOldWidth - Objects[i].FLeft);
    if Objects[i].Align = saBottomLeft then
      Objects[i].FTop := FHeight - (FOldHeight - Objects[i].FTop);
    if Objects[i].Align = saBottomRight then
    begin
      Objects[i].FLeft := FWidth - Objects[i].FLeft;
      Objects[i].FTop := FHeight - Objects[i].FTop;
    end;
  end;
end;

procedure TSeSkinObject.Invalidate;
begin
  if not Visible then Exit;

  if FParentControl <> nil then
    SendMessage(FParentControl.Handle, WM_INVALIDATESKINOBJECT, 0, Integer(Self));
end;

{ Drawing =====================================================================}

procedure TSeSkinObject.Draw(Canvas: TCanvas);
var
  i: integer;
  Child: TSeSkinObject;
begin
  if not Visible then Exit;
  if FWidth <= 0 then Exit;
  if FHeight <= 0 then Exit;

  if (Count = 0) or ((Count > 0) and (FDrawIfOwner)) then
  begin
    if FColor = clNone then
    begin

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?