cxsplitter.pas

来自「胜天进销存源码,国产优秀的进销存」· PAS 代码 · 共 1,764 行 · 第 1/5 页

PAS
1,764
字号
    property NativeBackground: Boolean read FNativeBackground write SetNativeBackground default True;
    property OnCanResize: TCanResizeEvent read FOnCanResize write FOnCanResize;
    property OnMoved: TNotifyEvent read FOnMoved write FOnMoved;
    property OnBeforeOpen: TBeforeOpenHotZoneEvent read FOnBeforeOpen write FOnBeforeOpen;
    property OnAfterOpen: TNotifyEvent read FOnAfterOpen write FOnAfterOpen;
    property OnBeforeClose: TBeforeCloseHotZoneEvent read FOnBeforeClose write FOnBeforeClose;
    property OnAfterClose: TNotifyEvent read FOnAfterClose write FOnAfterClose;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure OpenSplitter;
    procedure CloseSplitter;
    property State: TcxSplitterState read FState write SetSplitterState;
    function IsPointInHotZone(const X, Y: Integer): Boolean;
    function IsPointInSplitter(const X, Y: Integer): Boolean;
    property HotZoneStyleClass: TcxHotZoneStyleClass read FHotZoneStyleClass
      write SetHotZoneStyleClass;
    property Direction: TcxSplitterDirection read CalculateSplitterDirection;
  published
    property HotZoneClassName: string read GetHotZoneClassName write SetHotZoneClassName;
    property HotZone: TcxHotZoneStyle read FHotZone write SetHotZone;
    property HotZoneEvents: TNotifyEvent read FHotZoneEvents write FHotZoneEvents;
  end;

  { TcxSplitter }
  TcxSplitter = class(TcxCustomSplitter)
  published
    { Public declarations }
    property AlignSplitter;
    property AllowHotZoneDrag;
    property AutoPosition;
    property DragThreshold;
    property NativeBackground;
    property PositionAfterOpen;
    property AutoSnap;
    property InvertDirection;
    property MinSize;
    property ResizeUpdate;
    property ResizeIgnoreSnap; //deprecated
    property Control;
    property OnCanResize;
    property OnMoved;
    property OnBeforeOpen;
    property OnAfterOpen;
    property OnBeforeClose;
    property OnAfterClose;
    property Color;
    property ShowHint;
    property ParentColor;
    property ParentShowHint;
    property Visible;
  end;

function GetRegisteredHotZoneStyles: TcxRegisteredClasses;

implementation

uses
  cxContainer, dxThemeConsts, dxThemeManager, dxUxTheme;

type
  TWinControlAccess = class(TWinControl);

const
  SplitterDefaultSize = 8;

var
  FRegisteredHotZoneStyles: TcxRegisteredClasses;

function GetRegisteredHotZoneStyles: TcxRegisteredClasses;
begin
  if FRegisteredHotZoneStyles = nil then
    FRegisteredHotZoneStyles := TcxRegisteredClasses.Create;
  Result := FRegisteredHotZoneStyles;
end;

procedure DrawSplitterDots(ACanvas: TcxCanvas; const ARect: TRect; const AClicked: Boolean;
  const AFromLeftTop: Boolean; const ALightColor, AShadowColor: TColor;
  const ASplitterDirection: TcxSplitterDirection; const ABetweenPoints, AIndent: Integer);
var
  I, ANextDotPoint: Integer;

  procedure PaintOuterDot(X, Y: Integer);
  begin
    ACanvas.Brush.Color := ALightColor;
    ACanvas.FillRect(Rect(X, Y, X + 2, Y + 2));
    ACanvas.Brush.Color := AShadowColor;
    ACanvas.FillRect(Rect(X + 1, Y + 1, X + 3, Y + 3));
  end;

  procedure PaintInnerDot(X, Y: Integer);
  begin
    ACanvas.Brush.Color := ALightColor;
    ACanvas.FillRect(Rect(X + 1, Y + 1, X + 3, Y + 3));
    ACanvas.Brush.Color := AShadowColor;
    ACanvas.FillRect(Rect(X, Y, X + 2, Y + 2));
  end;

begin
  if AFromLeftTop = True then
  begin
    if (ASplitterDirection = cxsdLeftToRight) or (ASplitterDirection = cxsdRightToLeft) then
    begin
      ANextDotPoint := ARect.Top + ABetweenPoints;
      for I := ARect.Top + ABetweenPoints to ARect.Bottom - ABetweenPoints do
        if (I = ANextDotPoint) and ((I + ABetweenPoints) <= ARect.Bottom) then
        begin
          if AClicked = False then
            PaintOuterDot(ARect.Left + AIndent, I)
          else
            PaintInnerDot(ARect.Left + AIndent, I);
          Inc(ANextDotPoint, ABetweenPoints + 2);
        end;
    end
    else
    begin
      ANextDotPoint := ARect.Left + ABetweenPoints;
      for I := ARect.Left + ABetweenPoints to ARect.Right - ABetweenPoints do
        if (I = ANextDotPoint) and ((I + ABetweenPoints) <= ARect.Right) then
        begin
          if AClicked = False then
            PaintOuterDot(I, ARect.Top + AIndent)
          else
            PaintInnerDot(I, ARect.Top + AIndent);
          Inc(ANextDotPoint, ABetweenPoints + 2);
        end;
    end;
  end
  else
  begin
    if (ASplitterDirection = cxsdLeftToRight) or (ASplitterDirection = cxsdRightToLeft) then
    begin
      ANextDotPoint := ARect.Bottom - (ABetweenPoints * 2);
      for I := ARect.Bottom - (ABetweenPoints * 2) downto ARect.Top do
        if (I = ANextDotPoint) and (I >= ARect.Top) then
        begin
          if AClicked = False then
            PaintOuterDot(ARect.Left + AIndent, I)
          else
            PaintInnerDot(ARect.Left + AIndent, I);
          Dec(ANextDotPoint, ABetweenPoints + 2);
        end;
    end
    else
    begin
      ANextDotPoint := ARect.Right - (ABetweenPoints * 2);
      for I := ARect.Right - (ABetweenPoints * 2) downto ARect.Left do
        if (I = ANextDotPoint) and (I >= ARect.Left) then
        begin
          if AClicked = False then
            PaintOuterDot(I, ARect.Top + AIndent)
          else
            PaintInnerDot(I, ARect.Top + AIndent);
          Dec(ANextDotPoint, ABetweenPoints + 2);
        end;
    end;
  end;
end;

procedure DrawHotZoneArrow(ACanvas: TcxCanvas; const ARect: TRect;
  const AHighlighted, AClicked: Boolean; const ArrowColor, ArrowHighlightColor: TColor;
  const ASplitterDirection: TcxSplitterDirection);
var
  I, ADelta, ACenter, ARectSize: Integer;
  ALocalArrowColor: TColor;
begin
  if (AHighlighted = False) or (AClicked = True) then
    ALocalArrowColor := ArrowColor
  else
    ALocalArrowColor := ArrowHighlightColor;
  if (ASplitterDirection = cxsdLeftToRight) or (ASplitterDirection = cxsdRightToLeft) then
  begin
    ARectSize := ARect.Bottom - ARect.Top;
    if (ARectSize mod 2) <> 0 then Dec(ARectSize, 1);
    ACenter := (ARectSize div 2) + 1;
  end
  else
  begin
    ARectSize := ARect.Right - ARect.Left;
    if (ARectSize mod 2) <> 0 then Dec(ARectSize, 1);
    ACenter := (ARectSize div 2) + 1;
  end;
  case ASplitterDirection of
    cxsdLeftToRight:
    begin
      for I := 0 to 3 do
      begin
        if I = 3 then
          ADelta := 1
        else
          ADelta := 0;
        DrawCanvasLine(ACanvas.Canvas, ALocalArrowColor, Point(ARect.Left + 4 - I + ADelta,
          ARect.Top + ACenter - I), Point(ARect.Left + 6 - I, ARect.Top + ACenter - I));
        DrawCanvasLine(ACanvas.Canvas, ALocalArrowColor, Point(ARect.Left + 4 - I + ADelta,
          ARect.Top + ACenter + I), Point(ARect.Left + 6 - I, ARect.Top + ACenter + I));
      end;
    end;
    cxsdRightToLeft:
    begin
      for I := 0 to 3 do
      begin
        if I = 3 then
          ADelta := -1
        else
          ADelta := 0;
        DrawCanvasLine(ACanvas.Canvas, ALocalArrowColor, Point(ARect.Left + 2 + I,
          ARect.Top + ACenter - I), Point(ARect.Left + 4 + I + ADelta, ARect.Top + ACenter - I));
        DrawCanvasLine(ACanvas.Canvas, ALocalArrowColor, Point(ARect.Left + 2 + I,
          ARect.Top + ACenter + I), Point(ARect.Left + 4 + I + ADelta, ARect.Top + ACenter + I));
      end;
    end;
    cxsdTopToBottom:
    begin
      for I := 0 to 3 do
      begin
        if I = 3 then
          ADelta := 1
        else
          ADelta := 0;
        DrawCanvasLine(ACanvas.Canvas, ALocalArrowColor, Point(ARect.Left + ACenter - I,
          ARect.Top + 4 - I + ADelta), Point(ARect.Left + ACenter - I, ARect.Top + 6 - I));
        DrawCanvasLine(ACanvas.Canvas, ALocalArrowColor, Point(ARect.Left + ACenter + I,
          ARect.Top + 4 - I + ADelta), Point(ARect.Left + ACenter + I, ARect.Top + 6 - I));
      end;
    end;
    cxsdBottomToTop:
    begin
      for I := 0 to 3 do
      begin
        if I = 3 then
          ADelta := -1
        else
          ADelta := 0;
        DrawCanvasLine(ACanvas.Canvas, ALocalArrowColor, Point(ARect.Left + ACenter - I,
          ARect.Top + 2 + I), Point(ARect.Left + ACenter - I, ARect.Top + 4 + I + ADelta));
        DrawCanvasLine(ACanvas.Canvas, ALocalArrowColor, Point(ARect.Left + ACenter + I,
          ARect.Top + 2 + I), Point(ARect.Left + ACenter + I, ARect.Top + 4 + I + ADelta));
      end;
    end;
  end;
end;

{ TcxHotZoneStyle }
constructor TcxHotZoneStyle.Create(AOwner: TcxCustomSplitter);
begin
  inherited Create;
  FOwner := AOwner;
  FSizePercent := 30;
  FVisible := True;
end;

destructor TcxHotZoneStyle.Destroy;
begin
  FOwner := nil;
  inherited;
end;

procedure TcxHotZoneStyle.Assign(Source: TPersistent);
begin
  if (Source is TcxHotZoneStyle) then
  begin
    with (Source as TcxHotZoneStyle) do
    begin
      Self.SizePercent := SizePercent;
      Self.Visible := Visible;
    end;
  end
  else
    inherited Assign(Source);
end;

procedure TcxHotZoneStyle.Changed;
begin
  if Assigned(FOwner) then FOwner.HotZoneStyleChanged;
end;

function TcxHotZoneStyle.SplitterDirection: TcxSplitterDirection;
begin
  if Assigned(FOwner) then
    Result := FOwner.CalculateSplitterDirection
  else
    Result := Low(TcxSplitterDirection);
end;

procedure TcxHotZoneStyle.SetSizePercent(Value: TcxNaturalNumber);
begin
  if FSizePercent <> Value then
  begin
    FSizePercent := Value;
    Changed;
  end;
end;

procedure TcxHotZoneStyle.SetVisible(Value: Boolean);
begin
  if FVisible <> Value then
  begin
    FVisible := Value;
    Changed;
  end;
end;

function TcxHotZoneStyle.DrawHotZone(ACanvas: TcxCanvas; const ARect: TRect;
  const AHighlighted, AClicked: Boolean): TRect;
begin
  { Dummy }
end;

procedure TcxHotZoneStyle.DrawBackground(ACanvas: TcxCanvas; const ARect: TRect;
  const AHighlighted, AClicked: Boolean);
begin
  { Dummy }
end;

function TcxHotZoneStyle.GetMinSize: TcxNaturalNumber;
begin
  Result := SplitterDefaultSize;
end;

function TcxHotZoneStyle.GetMaxSize: TcxNaturalNumber;
begin
  Result := SplitterDefaultSize;
end;

function TcxHotZoneStyle.CalculateHotZoneRect(const ABounds: TRect): TRect;
var
  ARect : TRect;
  AHotZoneRectSize, APos: Integer;
begin
  ARect := ABounds;
  if (SplitterDirection = cxsdLeftToRight) or (SplitterDirection = cxsdRightToLeft) then
  begin
    ARect.Right := ARect.Left + SplitterDefaultSize - 1;
    AHotZoneRectSize := ((ARect.Bottom - ARect.Top) * SizePercent) div 100;
    APos := ((ARect.Bottom - ARect.Top) div 2) - (AHotZoneRectSize div 2);
    Result := Rect(ARect.Left, APos, ARect.Right, APos + AHotZoneRectSize);
  end
  else
  begin
    ARect.Bottom := ARect.Top + SplitterDefaultSize - 1;
    AHotZoneRectSize := ((ARect.Right - ARect.Left) * SizePercent) div 100;
    APos := ((ARect.Right - ARect.Left) div 2) - (AHotZoneRectSize div 2);
    Result := Rect(APos, ARect.Top, APos + AHotZoneRectSize, ARect.Bottom);
  end;
  HotZoneRect := Result;
end;
{ TcxHotZoneStyle }

{ TcxMediaPlayer9Style }
constructor TcxMediaPlayer9Style.Create(AOwner: TcxCustomSplitter);
begin
  inherited Create(AOwner);

⌨️ 快捷键说明

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