⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spagecontrol.pas

📁 Alpha Controls 界面控件包
💻 PAS
📖 第 1 页 / 共 4 页
字号:
unit sPageControl;
{$I sDefs.inc}
{.$DEFINE LOGGED}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, sCommonData, sConst, sFade, sUpDown, extctrls, sSpeedButton
  {$IFDEF TNTUNICODE}, TntComCtrls, TntGraphics{$ENDIF};

type
{$IFNDEF NOTFORHELP}
  TacCloseAction = (acaHide, acaFree);
  TacCloseBtnClick = procedure(Sender: TComponent; TabIndex : integer; var CanClose: boolean; var Action: TacCloseAction) of object;

  TsPageControl = class;

  TsTabSkinData = class(TPersistent)
  private
    FCustomColor: boolean;
    FCustomFont: boolean;
    FSkinSection: string;
    procedure SetCustomColor(const Value: boolean);
    procedure SetCustomFont(const Value: boolean);
    procedure SetSkinSection(const Value: string);
  published
    property CustomColor : boolean read FCustomColor write SetCustomColor;
    property CustomFont : boolean read FCustomFont write SetCustomFont;
    property SkinSection : TsSkinSection read FSkinSection write SetSkinSection;
  end;

  TsTabSheet = class;

  TsTabBtn = class(TsSpeedButton)
  public
    Page : TsTabSheet;
    constructor Create(AOwner:TComponent); override;
    procedure UpdateGlyph;
  end;

{$IFDEF TNTUNICODE}
  TsTabSheet = class(TTntTabSheet)                  
{$ELSE}
  TsTabSheet = class(TTabSheet)
{$ENDIF}
  private
    FTabSkin: TsSkinSection;
    FButtonSkin: TsSkinSection;
    FUseCloseBtn: boolean;
    FCommonData: TsTabSkinData;
    procedure SetUseCloseBtn(const Value: boolean);
    procedure SetButtonSkin(const Value: TsSkinSection);
    procedure SetTabSkin(const Value: TsSkinSection);
  public
    Btn : TsTabBtn;
    constructor Create(AOwner:TComponent); override;
    procedure CreateParams(var Params: TCreateParams); override;
    destructor Destroy; override;
    procedure WMPaint (var Message: TWMPaint); message WM_PAINT;
    procedure WndProc (var Message: TMessage); override;
  published
    property SkinData : TsTabSkinData read FCommonData write FCommonData;
    property ButtonSkin : TsSkinSection read FButtonSkin write SetButtonSkin;
    property TabSkin : TsSkinSection read FTabSkin write SetTabSkin;
    property UseCloseBtn : boolean read FUseCloseBtn write SetUseCloseBtn default True;
  end;
{$ENDIF}

{$IFDEF TNTUNICODE}
  TsPageControl = class(TTntPageControl)
{$ELSE}
  TsPageControl = class(TPageControl)
{$ENDIF}
{$IFNDEF NOTFORHELP}
  private
    StoredVisiblePageCount : integer;
    ChangedSkinSection : string;
    FCommonData: TsCommonData;
    UpDown: TsUpDown;
    FAnimatEvents: TacAnimatEvents;
    procedure CheckUpDown;
    function  GetInVisibleItemCount: Integer;
    procedure OnUpDownClick(Sender: TObject; Button: TUDBtnType);
    procedure UpdateUpDown;
    procedure UpdateUpDownRgn(Repaint : boolean = False);
    procedure ShowSkinUpDown;

    procedure CMHintShow(var Message: TMessage); message CM_HINTSHOW; // v4.42
    procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
    procedure WMPaint (var Message: TWMPaint); message WM_PAINT;
    procedure DrawSkinTabs(CI : TCacheInfo);
    procedure DrawSkinTab(PageIndex: Integer; State : integer; Bmp : TBitmap; OffsetPoint : TPoint); overload;
    procedure DrawSkinTab(PageIndex: Integer; State : integer; DC : hdc); overload;
    function PageRect: TRect;
    function TabsRect: TRect;
    function GlyphRect: TRect;
    function SkinTabRect(Index : integer; Active : boolean) : TRect;
    function TabRow(TabIndex : integer) : integer;
    function GetActivePage: TsTabSheet;
    procedure SetActivePage(const Value: TsTabSheet);
    procedure UpdateBtnData;
    procedure PaintButtonEx(TabIndex : integer; BtnState : integer; TabState : integer);
    procedure PaintButtons(DC : hdc);
    function BtnRect(TabIndex : integer) : TRect;
  private
    FShowCloseBtns: boolean;
    FOnCloseBtnClick: TacCloseBtnClick;
    FCloseBtnSkin: TsSkinSection;
    procedure SetShowCloseBtns(const Value: boolean);
    procedure SetCloseBtnSkin(const Value: TsSkinSection);
  protected
    BtnIndex : integer;
    CurItem : integer;
    BtnWidth : integer;
    BtnHeight : integer;
    TabsChanging : boolean;
    procedure PaintButton(DC : hdc; TabRect : TRect; State : integer; BG : hdc = 0); virtual;
    function GetTabUnderMouse(p : TPoint) : integer;
    procedure RepaintTab(i, State : integer; TabDC : hdc = 0);
    procedure RepaintTabs(DC : HDC; ActiveTabNdx : integer);
    function VisibleTabsCount : integer;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure WndProc (var Message: TMessage); override;
    procedure Loaded; override;
    procedure AfterConstruction; override;
    procedure UpdateActivePage; override;
    procedure CloseClick(Sender: TObject);
    procedure ArrangeButtons;
  published
    property ActivePage: TsTabSheet read GetActivePage write SetActivePage; // v4.27
    property AnimatEvents : TacAnimatEvents read FAnimatEvents write FAnimatEvents default [aeGlobalDef];
    property Style;
{$ENDIF}
    property CloseBtnSkin : TsSkinSection read FCloseBtnSkin write SetCloseBtnSkin;
    property ShowCloseBtns : boolean read FShowCloseBtns write SetShowCloseBtns default False;
    property SkinData : TsCommonData read FCommonData write FCommonData;
    property OnCloseBtnClick: TacCloseBtnClick read FOnCloseBtnClick write FOnCloseBtnClick;
  end;

implementation

uses sMessages, sVclUtils, acUtils, sMaskData, sStyleSimply, math, Commctrl, sSkinProps, sAlphaGraph,
  sGraphUtils, sTabControl, sSkinManager {$IFDEF LOGGED}, sDebugMsgs{$ENDIF};

{ TsPageControl }

const
  BtnOffs = 1;
  iBtnWidth = 15;
  iBtnHeight = 15;

var
  acBtnPressed : boolean = False;

procedure TsPageControl.AfterConstruction;
begin
  inherited;                                                         
  SkinData.Loaded;
end;

procedure TsPageControl.CheckUpDown;
var
  Wnd : HWND;
  i : Integer;
begin
  if (csLoading in ComponentState) or (csCreating in ControlState) then Exit;
  if FCommonData.Skinned then begin
    Wnd := FindWindowEx(Handle, 0, 'msctls_updown32', nil);
    if Wnd <> 0 then DestroyWindow(Wnd);
    i := GetInVisibleItemCount;
    if TabPosition in [tpLeft, tpRight] then i := 0;
    if (i < 1) or Multiline then begin
      if (UpDown <> nil) then FreeAndNil(UpDown)
    end
    else if (UpDown = nil) then ShowSkinUpDown else UpdateUpDown;
  end
  else if UpDown <> nil then FreeAndNil(UpDown);
end;

procedure TsPageControl.CMHintShow(var Message: TMessage);
var
  Item : integer;
  P : TPoint;
begin
  with TCMHintShow(Message) do begin
    Item := GetTabUnderMouse(Point(HintInfo.CursorPos.X, HintInfo.CursorPos.Y));
    if Item <> -1 then begin
      with HintInfo^ do begin
        P := ClientToScreen(HintInfo.CursorPos);
        P.X := P.X + GetSystemMetrics(SM_CXCURSOR) div 2;
        P.Y := P.Y + GetSystemMetrics(SM_CYCURSOR) div 2;
        HintInfo.HintPos := P;
        HintInfo.HintStr := Pages[Item].Hint;
        Message.Result := 0;
      end;
    end;
  end;
end;

procedure TsPageControl.CNNotify(var Message: TWMNotify);
begin
  if FCommonData.Skinned then case Message.NMHdr^.code of
    TCN_SELCHANGE : begin
      inherited;
      UpdateUpDown;
      if not (csDesigning in ComponentState) and FCommonData.SkinManager.AnimEffects.PageChange.Active then begin
        AnimShowControl(Self, FCommonData.SkinManager.AnimEffects.PageChange.Time);
        SkinData.BGChanged := True;
        if ActivePage <> nil then RedrawWindow(ActivePage.Handle, nil, 0, RDW_INVALIDATE or RDW_UPDATENOW or RDW_ALLCHILDREN);
      end;
      Exit;
    end;
    TCN_SELCHANGING : begin
      if not (csDesigning in ComponentState) and FCommonData.SkinManager.AnimEffects.PageChange.Active then begin
        PrepareForAnimation(Self);
      end;
      UpdateUpDown;
    end;
  end;
  inherited;
  if FCommonData.Skinned then case Message.NMHdr^.code of
    TCN_SELCHANGING : begin
      if Message.Result = 1 then begin
        SendMessage(Handle, WM_SETREDRAW, 1, 0);
        if ow <> nil then FreeAndNil(ow);
        SendMessage(Handle, WM_MOUSEMOVE, 0, 0);
      end;
    end;
  end;
end;

constructor TsPageControl.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FCommonData := TsCommonData.Create(Self, True);
  FCommonData.COC := COC_TsPageControl;
  TabsChanging := False;
  FAnimatEvents := [aeGlobalDef];
  FShowCloseBtns := False;
  CurItem := -1;
end;

destructor TsPageControl.Destroy;
begin
  if Assigned(FCommonData) then FreeAndNil(FCommonData);
  inherited Destroy;
end;

procedure TsPageControl.DrawSkinTab(PageIndex, State: integer; Bmp : TBitmap; OffsetPoint : TPoint);
var
  rText, aRect, R : TRect;
  VertFont : TLogFont;
  pFont : PLogFontA;
  i, h, w : integer;
  CI : TCacheInfo;
  TabIndex, TabMask, TabState : integer;
  TabSection : string;
  TempBmp : Graphics.TBitmap;
  SavedDC : hdc;

  lCaption: ACString;

  procedure MakeVertFont(Orient : integer);
  begin
    pFont := @VertFont;
    VertFont.lfFaceName := 'Arial';
    GetObject(Bmp.Canvas.Handle, SizeOf(TLogFont), pFont);
    VertFont.lfEscapement := Orient;
    VertFont.lfHeight := Font.Height;
    VertFont.lfStrikeOut := integer(fsStrikeOut in Font.Style);
    VertFont.lfItalic := integer(fsItalic in Font.Style);
    VertFont.lfUnderline := integer(fsUnderline	in Font.Style);
    VertFont.lfWeight := FW_NORMAL;
    VertFont.lfCharSet := Font.Charset;

    VertFont.lfWidth := 0;
    Vertfont.lfOutPrecision := OUT_DEFAULT_PRECIS;
    VertFont.lfClipPrecision := CLIP_DEFAULT_PRECIS;
    VertFont.lfOrientation := VertFont.lfEscapement;
    VertFont.lfPitchAndFamily := Default_Pitch;
    VertFont.lfQuality := Default_Quality;
    Bmp.Canvas.Font.Handle := CreateFontIndirect(VertFont);
    if State <> 0
      then Bmp.Canvas.Font.Color := FCommonData.SkinManager.gd[TabIndex].HotFontColor[1]
      else Bmp.Canvas.Font.Color := FCommonData.SkinManager.gd[TabIndex].FontColor[1];
  end;
  procedure KillVertFont; begin Bmp.Canvas.Font.Assign(Font) end;
begin
  R := SkinTabRect(Pages[PageIndex].TabIndex, PageIndex = ActivePageIndex);
  if (PageIndex = -1) or ((State = 1) and (R.Left < 0)) then Exit;
  if not Pages[PageIndex].TabVisible then Exit;

  rText := SkinTabRect(Pages[PageIndex].TabIndex, (State = 2) and (Pages[PageIndex] = ActivePage));
  aRect := rText;

  // Tabs drawing
  if FCommonData.SkinManager.ConstData.IndexTabTop > 0 then begin // new style
    TabState := State;
    case Style of
      tsTabs : begin
        if TsTabSheet(Pages[PageIndex]).TabSkin <> '' then begin
          TabSection := TsTabSheet(Pages[PageIndex]).TabSkin;
          TabIndex := FCommonData.SkinManager.GetSkinIndex(TabSection);
          TabMask := FCommonData.SkinManager.GetMaskIndex(TabSection, s_BordersMask);
        end
        else case TabPosition of // Init of skin data
          tpTop : begin TabIndex := FCommonData.SkinManager.ConstData.IndexTabTop; TabMask := FCommonData.SkinManager.ConstData.MaskTabTop; TabSection := s_TabTop end;
          tpLeft : begin TabIndex := FCommonData.SkinManager.ConstData.IndexTabLeft; TabMask := FCommonData.SkinManager.ConstData.MaskTabLeft; TabSection := s_TabLeft end;
          tpBottom : begin TabIndex := FCommonData.SkinManager.ConstData.IndexTabBottom; TabMask := FCommonData.SkinManager.ConstData.MaskTabBottom; TabSection := s_TabBottom end
          else begin TabIndex := FCommonData.SkinManager.ConstData.IndexTabRight; TabMask := FCommonData.SkinManager.ConstData.MaskTabRight; TabSection := s_TabRight end;
        end;
      end;
      tsButtons : begin
        if TsTabSheet(Pages[PageIndex]).TabSkin <> '' then TabSection := TsTabSheet(Pages[PageIndex]).TabSkin else TabSection := s_Button;
        TabIndex := FCommonData.SkinManager.GetSkinIndex(TabSection);
        TabMask := FCommonData.SkinManager.GetMaskIndex(TabSection, s_BordersMask);
      end
      else begin
        if TsTabSheet(Pages[PageIndex]).TabSkin <> '' then TabSection := TsTabSheet(Pages[PageIndex]).TabSkin else TabSection := s_ToolButton;
        TabIndex := FCommonData.SkinManager.GetSkinIndex(TabSection);
        TabMask := FCommonData.SkinManager.GetMaskIndex(TabSection, s_BordersMask);
      end;
    end;

    if FCommonData.SkinManager.IsValidImgIndex(TabMask) then begin // Drawing of tab
      TempBmp := CreateBmp24(WidthOf(aRect), HeightOf(aRect));
      try
        if (State = 2) and (Pages[PageIndex] = ActivePage) then begin
          // Restore BG for Active tab
          BitBlt(TempBmp.Canvas.Handle, aRect.Left + OffsetPoint.x, aRect.Top + OffsetPoint.y, TempBmp.Width, TempBmp.Height,
                   FCommonData.FCacheBmp.Canvas.Handle, aRect.Left, aRect.Top, SRCCOPY);
          OffsetRect(R, OffsetPoint.X, OffsetPoint.Y);
          if ParentCenterColor <> clFuchsia then FillDC(TempBmp.Canvas.Handle, R, ColorToRGB(ParentCenterColor))
          else begin
            CI := GetParentCache(FCommonData);
            if CI.Ready
              then BitBlt(TempBmp.Canvas.Handle, R.Left, R.Top, WidthOf(R), HeightOf(R),
                          CI.Bmp.Canvas.Handle, CI.X + Left + TabRect(Pages[PageIndex].TabIndex).Left,
                          CI.Y + Top + TabRect(Pages[PageIndex].TabIndex).Top, SRCCOPY)
              else FillDC(TempBmp.Canvas.Handle, R, ColorToRGB(TsHackedControl(Parent).Color));
          end;
          // Paint active tab
          BitBlt(Bmp.Canvas.Handle, aRect.Left + OffsetPoint.x, aRect.Top + OffsetPoint.y, TempBmp.Width, TempBmp.Height, TempBmp.Canvas.Handle, 0, 0, SRCCOPY);
          CI := MakeCacheInfo(TempBmp);
          PaintItem(TabIndex, TabSection, CI, True, TabState, Rect(0, 0, TempBmp.Width, TempBmp.Height),
                           Point(0, 0), Bmp, FCommonData.SkinManager);
        end
        else begin
          CI := MakeCacheInfo(FCommonData.FCacheBmp);
          if State = 1 then CI.X := 0;
          PaintItem(TabIndex, TabSection, CI, True, TabState, Rect(0, 0, TempBmp.Width, TempBmp.Height),
                           Point(aRect.Left, aRect.Top), TempBmp, FCommonData.SkinManager);

          SavedDC := SaveDC(Bmp.Canvas.Handle);
          R := PageRect;
          if TabPosition in [tpLeft, tpTop] then ExcludeClipRect(Bmp.Canvas.Handle, R.Left, R.Top, R.Right, R.Bottom);
          BitBlt(Bmp.Canvas.Handle, aRect.Left + OffsetPoint.x, aRect.Top + OffsetPoint.y, TempBmp.Width, TempBmp.Height, TempBmp.Canvas.Handle, 0, 0, SRCCOPY);
          RestoreDC(Bmp.Canvas.Handle, SavedDC);
        end;
      finally
        FreeAndNil(TempBmp);
      end;
    end;
  end;

  // End of tabs drawing
  if not OwnerDraw then begin
    // Drawing of the tab content
    OffsetRect(rText, OffsetPoint.x, OffsetPoint.y);

    {$IFDEF TNTUNICODE}
     if Pages[PageIndex] is TTntTabSheet then
        lCaption := TTntTabSheet(Pages[PageIndex]).Caption
     else
    {$ENDIF}
        lCaption := Pages[PageIndex].Caption;

    R := rText;
    InflateRect(R, -3, -3);
    case TabPosition of
      tpTop, tpBottom : begin
        Bmp.Canvas.Font.Assign(Font);
        if (Images <> nil) and (Pages[PageIndex].ImageIndex > -1) and (Pages[PageIndex].ImageIndex <= Images.Count - 1) then begin
          Images.Draw(Bmp.Canvas,
                rText.Left + (WidthOf(rText) - (acTextWidth(Bmp.Canvas, lCaption) + Images.Width + 8)) div 2,
                rText.Top + (HeightOf(rText) - Images.Height) div 2,
                Pages[PageIndex].ImageIndex,
                True);
          inc(rText.Left, WidthOf(GlyphRect));
          R := rText;
{$IFDEF TNTUNICODE}
          WriteTextExW(Bmp.Canvas, PACChar(lCaption),
              Enabled, rText, DT_CENTER or DT_SINGLELINE or DT_VCENTER, TabIndex, State <> 0, FCommonData.SkinManager);
{$ELSE}
          WriteTextEx(Bmp.Canvas, PACChar(lCaption),
              Enabled, rText, DT_CENTER or DT_SINGLELINE or DT_VCENTER, TabIndex, State <> 0, FCommonData.SkinManager);
{$ENDIF}

        end
        else begin
          R := rText;

⌨️ 快捷键说明

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