11

Delphi 是否有滑动(动画)面板组件?

例如,它可以在Raize Components(带有“热点”或隐藏/显示按钮的左侧面板)中找到。

我不需要一个可调整大小的面板,而是一个可以从左到右水平平滑滑动的面板 + 有一个隐藏/显示按钮(如果没有那个按钮,这没什么大不了的)。

谢谢!

4

5 回答 5

22

试试NLDSideBar,这是一个我自己编写的容器组件,它可以折叠并沿其父级的左侧或右侧对齐。

界面:

property Align: TSideBarAlign default alLeft;
property AutoHide: Boolean default False;
property Hint: String;
property MinWidth: Integer default DefWidth;
property OnAutoHideChanged: TNotifyEvent;
property OnHide: TNotifyEvent;
property PinButtonDownHint: String;
property PinButtonUpHint: String;
property PinButtonVisible: Boolean default True;
property Resizable: Boolean default True;
property SideButtonWidth: Integer default DefSideButtonWidth;
property Caption;
property Color default clBtnFace;
property Font;
property ParentColor default False;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property TabOrder;
property TabStop;

NLDSideBar

或者也许这个旧版本是动画的。免费使用,免费修改。

很抱歉自我推销,但我认为这是对问题的回答。

于 2011-09-01T05:08:19.937 回答
11

我们最终建立了自己的控制。我们找不到任何符合我们要求的东西。结果没那么难。我确信有些情况我们没有正确处理,但是这对我们很有用。

下面的代码使用 cxGroupBox,因为我们需要它来匹配我们应用程序的其余部分。可以将其切换为普通的 GroupBox。

我们在两个地方使用它。在一种情况下,我们在标准的 Delphi Flow Panel 中有许多这样的面板(我不确定添加了哪个版本)。当我们的 DynPanel 折叠时,所有东西都会自动向上移动并填充空间。

在另一种情况下,我们有一个分为主要部分和工具箱的窗口。两者由标准分离器隔开。主窗口设置为与客户端对齐。当我们的面板折叠或展开时。拆分器会自动移动并扩展主要部分。

我们从来没有完全让“容器”控件工作,因此您添加到面板的项目可以移动到您通常期望在组框中的范围之外。但这不会给我们带来任何重大问题,所以我们就离开了。这也没有考虑与按钮大小相关的 DPI 变化。标题会变大,但按钮不会。


unit DynPanel;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, cxGroupBox;

const
  DEFAULTBUTTONWIDTH = 16;
  DEFAULTWIDTH  = 161;
  DEFAULTHEIGHT = 81;
  cButtonPadding = 8;
  cCollapsePadding = 3;
  cCaptionPadding = '       ';
  cCollapsedSize = DEFAULTBUTTONWIDTH + cCollapsePadding;
  cAutoCollapseSize = DEFAULTBUTTONWIDTH + cButtonPadding;

type
  TCollapseDirection = (cdUp, cdRight, cdLeft);

  TMinDemension = cAutoCollapseSize..High(Integer);

  TDynPanel = class(TPanel)
  private
    FGroupBox: TcxGroupBox;
    FButtonPanel: TPanel;
    FButtonImage: TImage;

    FExpand: Boolean;
    FOldHeight: Integer;
    FOldWidth: Integer;
    FCollapseDirection: TCollapseDirection;
    FOrigGroupBoxCaption: String;
    FAutoCollapseHeight: TMinDemension;
    FAutoCollapseWidth: TMinDemension;

    FButtonPadding: integer;
    FCollapsePadding: integer;
    FCollapsedSize: integer;

    procedure SetExpand(Value: Boolean);
    procedure SetGroupBoxCaption(Value: string);
    procedure ButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure CMShowingChanged(var Message: TMessage); message CM_SHOWINGCHANGED;
    procedure EnableControls(Value: Boolean);
    procedure SetCollapseDirection(Value: TCollapseDirection);
    procedure ConfigurePanel;
    procedure SetMinHeight(Value: TMinDemension);
    procedure SetMinWidth(Value: TMinDemension);
    procedure UpdateImage();

  protected
    procedure Resize; override;
    procedure ChangeScale(M, D: Integer); override;
  public
    constructor Create(AOwner: TComponent); override;
    property OldHeight: Integer read FOldHeight write FOldHeight;
    property OldWidth: Integer read FOldWidth write FOldWidth;
    property GroupBox: TcxGroupBox read FGroupBox;
  published
    property Caption: string read FOrigGroupBoxCaption write SetGroupBoxCaption;
    property Expand: Boolean read FExpand write SetExpand;
    property BevelOuter default bvNone;
    property CollapseDirection: TCollapseDirection read FCollapseDirection write SetCollapseDirection default cdUp;
    property AutoCollapseHeight: TMinDemension read FAutoCollapseHeight write SetMinHeight default cAutoCollapseSize;
    property AutoCollapseWidth: TMinDemension read FAutoCollapseWidth write SetMinWidth default cAutoCollapseSize;
  end;

procedure Register;

implementation

{$R 'ButtonImages\ButtonImages.res' 'ButtonImages\ButtonImages.rc'}

uses cxEdit;

procedure Register;
begin
  RegisterComponents('AgWare', [TDynPanel]);
end;


{ TDynPanel }

{
  TDynPanel.Create
  ---------------------------------------------------------------------------
}
constructor TDynPanel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  Self.ControlStyle := ControlStyle - [csSetCaption];

  Self.Width := DEFAULTWIDTH;
  Self.Height := DEFAULTHEIGHT;
  BevelOuter := bvNone;

  FExpand := True;
  FOldHeight := Self.Height;
  FOldWidth := Self.Width;
  FOrigGroupBoxCaption := 'AgDynPanel';
  FCollapseDirection := cdUp;
  FAutoCollapseHeight := cAutoCollapseSize;
  FAutoCollapseWidth := cAutoCollapseSize;

  FGroupBox := TcxGroupBox.Create(Self);
  FGroupBox.Parent := Self;
  FGroupBox.Align := alClient;
  FGroupBox.Alignment := alTopLeft;

  FButtonPanel := TPanel.Create(Self);
  FButtonPanel.Parent := Self;
  FButtonPanel.Top := 0;
  FButtonPanel.Width := DEFAULTBUTTONWIDTH;
  FButtonPanel.Height := DEFAULTBUTTONWIDTH;
  FButtonPanel.Left := Width - DEFAULTBUTTONWIDTH - FButtonPadding;
  FButtonPanel.OnMouseDown := ButtonMouseDown;

  FButtonImage := TImage.Create(Self);
  FButtonImage.Parent := FButtonPanel;
  FButtonImage.Align := alClient;
  FButtonImage.Stretch := false;
  FButtonImage.Center := true;
  FButtonImage.OnMouseDown := ButtonMouseDown;

  UpdateImage;

  // The click should also work for the entire top of the group box.
  FGroupBox.OnMouseDown := ButtonMouseDown;

  FGroupBox.Caption := FOrigGroupBoxCaption;
  FGroupBox.Style.Font.Style := FGroupBox.Style.Font.Style + [fsBold];

  FButtonPadding := cButtonPadding;
  FCollapsePadding := cCollapsePadding;
  FCollapsedSize := cCollapsedSize;

end;

{
  TDynPanel.SetGroupBoxCaption
  ---------------------------------------------------------------------------
}
procedure TDynPanel.SetGroupBoxCaption(Value: String);
begin
  FOrigGroupBoxCaption := Value;
  ConfigurePanel;
end;

{
  TDynPanel.SetMinHeight
  ---------------------------------------------------------------------------
}
procedure TDynPanel.SetMinHeight(Value: TMinDemension);
begin
  if Value = FAutoCollapseHeight then
    Exit; // >>----->

  FAutoCollapseHeight := Value;

  if Showing then
    Resize;
end;

{
  TDynPanel.SetMinWidth
  ---------------------------------------------------------------------------
}
procedure TDynPanel.SetMinWidth(Value: TMinDemension);
begin
  if Value = FAutoCollapseWidth then
    Exit; // >>----->

  FAutoCollapseWidth := Value;

  if Showing then
    Resize;
end;

{
  TDynPanel.ButtonMouseDown
  ---------------------------------------------------------------------------
}
procedure TDynPanel.ButtonMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  if Button  mbLeft then
    Exit; // >>----->

  if ((FExpand = True) and (Y  FCollapsePadding)) or
     ((FExpand = False) and (FCollapseDirection = cdLeft) and (X >----->

  FExpand := Value;

  //ConfigurePanel;

  //--------------------------------------------------------------------------
  // Set the group box size
  //--------------------------------------------------------------------------
  //
  // I chose to do the resizing of the control here rather than in
  // ConfigurePanel because if you do it there the SetBounds will call ReSize
  // which will call ConfigurePanel again so that you would need to keep track
  // of a boolean variable to determine if you are making recursive calls into
  // ConfigurePanel. That is one reason. Another is that when the dfm values
  // are streamed in and the properties get set you will resize the control
  // before the actual Height and Width properties are set. This will cause
  // bogus default values to be stored for FOldHeight and FOldWidth and when
  // the control is displayed the dimensions will be wrong. If you size the
  // control here then, on creation, Resize will not get called and the
  // FOldHeight and FOldWidth values will not get saved off until
  // CMShowingChanged will explicitly call ReSize after the dimensions are
  // properly set. If you move this code into ConfigurePanel then when the
  // caption is streamed in and set from the dfm then ConfigurePanel would get
  // called, we would SetBounds there and then Resize would fire storing off the
  // default invalid values for the FOld variables as mentioned above.
  // Hope this makes sense. Leave the SetBounds calls here and make your life
  // easier. :)
  //--------------------------------------------------------------------------

  // Changing to Expanded
  if FExpand = True then
  begin
    // Up
    if FCollapseDirection = cdUp then
      SetBounds(Left, Top, Width, FOldHeight)
    // Right
    else if FCollapseDirection = cdRight then
      SetBounds((Left + Width) - FOldWidth, Top, FOldWidth, Height)
    // Left
    else if FCollapseDirection = cdLeft then
      SetBounds(Left, Top, FOldWidth, Height);
  end
  // Changing to Collapsed
  else
  begin
    // Up
    if FCollapseDirection = cdUp then
    begin
      // Reset the AutoCollapseHeight just to make sure we don't try to
      // recollapse on resize.
      if FAutoCollapseHeight  FGroupBox) and
       (Self.Controls[i]  FButtonPanel) then
    begin
      Self.Controls[i].Enabled := Value;
      Self.Controls[i].Visible := Value;
    end;
  end;
end;

{
  TDynPanel.CMShowingChanged
  ---------------------------------------------------------------------------
}
procedure TDynPanel.CMShowingChanged(var Message: TMessage);
begin
  inherited;
  if Showing then
    Resize;
end;

{
  TDynPanel.Resize
  ---------------------------------------------------------------------------
}
procedure TDynPanel.Resize;
begin

  if FExpand = True then
  begin
    if (FCollapseDirection = cdUp) and (Height  FAutoCollapseHeight then
      begin
        FOldHeight := Height;
        Expand := True;
      end
      else
        Height := FCollapsedSize;
    end
    else if (FCollapseDirection = cdLeft) or (FCollapseDirection = cdRight) then
    begin
      if (Width > FAutoCollapseWidth) then
      begin
        FOldWidth := Width;
        Expand := True;
      end
      else
        Width := FCollapsedSize;
    end;
  end;

  ConfigurePanel;

end;


{
  TDynPanel.ChangeScale
  ---------------------------------------------------------------------------
}
procedure TDynPanel.ChangeScale(M, D: Integer);
begin

  FAutoCollapseHeight := MulDiv(FAutoCollapseHeight, M, D);
  FAutoCollapseWidth := MulDiv(FAutoCollapseWidth, M, D);

  FButtonPadding := MulDiv(FButtonPadding, M, D);
  FCollapsePadding := MulDiv(FCollapsePadding, M, D);
  FCollapsedSize := MulDiv(FCollapsedSize, M, D);


  FOldHeight := MulDiv(FOldHeight, M, D);
  FOldWidth := MulDiv(FOldWidth, M, D);

  // inherited will cause resize to be called.  I need to update
  // my internal values before that happens, otherwise I will resize based
  // on the old values.
  inherited;

end;

{
  TDynPanel.SetCollapseDirection
  ---------------------------------------------------------------------------
}
procedure TDynPanel.SetCollapseDirection(Value: TCollapseDirection);
begin
  if Value = FCollapseDirection then
    Exit; // >>----->

  FCollapseDirection := Value;

  ConfigurePanel;
end;

{
  TDynPanel.ConfigurePanel
  ---------------------------------------------------------------------------
}
procedure TDynPanel.ConfigurePanel;
begin
  //--------------------------------------------------------------------------
  // Set the group box style, caption alignment, caption, button position, and
  // button image
  //--------------------------------------------------------------------------

  // Changing to Expanded
  if FExpand = True then
  begin
    FGroupBox.Style.Color := clWhite;
    // Up
    if FCollapseDirection = cdUp then
    begin
      FGroupBox.Alignment := alTopLeft;
      FGroupBox.Caption := FOrigGroupBoxCaption;
      FButtonPanel.Top := 0;
      FButtonPanel.Left := Width - FButtonPanel.Width - FButtonPadding;
    end
    // Right
    else if FCollapseDirection = cdRight then
    begin
      FGroupBox.Alignment := alTopLeft;
      FGroupBox.Caption := '       ' + FOrigGroupBoxCaption;
      FButtonPanel.Top := 0;
      FButtonPanel.Left := FButtonPadding;
    end
    // Left
    else if FCollapseDirection = cdLeft then
    begin
      FGroupBox.Alignment := alTopLeft;
      FGroupBox.Caption := FOrigGroupBoxCaption;
      FButtonPanel.Top := 0;
      FButtonPanel.Left := Width - FButtonPanel.Width - FButtonPadding;
    end;
  end
  // Changing to Collapsed
  else
  begin
    FGroupBox.Style.Color := clGradientActiveCaption;
    // Up
    if FCollapseDirection = cdUp then
    begin
      FGroupBox.Alignment := alTopLeft;
      FGroupBox.Caption := FOrigGroupBoxCaption;
      FButtonPanel.Top := 0;
      FButtonPanel.Left := Width - FButtonPanel.Width - FButtonPadding;
    end
    // Right
    else if FCollapseDirection = cdRight then
    begin
      FGroupBox.Alignment := alRightTop;
      FGroupBox.Caption := '       ' + FOrigGroupBoxCaption;
      FButtonPanel.Top := FButtonPadding;
      FButtonPanel.Left := FCollapsePadding;
    end
    // Left
    else if FCollapseDirection = cdLeft then
    begin
      FGroupBox.Alignment := alLeftTop;
      FGroupBox.Caption := FOrigGroupBoxCaption + '       ';
      FButtonPanel.Top := FButtonPadding;
      FButtonPanel.Left := 0;
    end;
  end;

  UpdateImage;
  // Now draw the button and invalidate Self
  Self.Invalidate;
end;

{
  TDynPanel.UpdateImage
  ---------------------------------------------------------------------------
}
procedure TDynPanel.UpdateImage();
begin
  case FCollapseDirection of
    cdUp:
      begin
        if FExpand = true then
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageUp')
        else
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageDown');
      end;
    cdLeft:
      begin
        if FExpand = true then
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageLeft')
        else
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageRight');
      end;
    cdRight:
      begin
        if FExpand = true then
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageRight')
        else
          FButtonImage.Picture.Bitmap.LoadFromResourceName(HInstance, 'ButtonImageLeft');
      end;
  end;

end;

end.

靠近左边
左开 左关闭

靠近顶部
顶开


顶部封闭

于 2011-09-01T03:06:28.630 回答
5

新的 Delphi 版本将包括这种滑动面板(通过 FireMonkey 的集成,以前称为 vgScene/dxScene)。您只需单击高度或位置道具,一个选项将允许为此创建动画,并带有各种选项(插值类型、持续时间等)。

在此处输入图像描述

于 2011-09-01T11:22:21.223 回答
5

从 2009 版开始,有一个TCategoryPanelGroup,您可以在其中添加 TCategoryPanel。
在此处输入图像描述

于 2011-09-04T15:36:20.813 回答
2

FoldingPanel
请在此处查看 FoldingPanel v1.3:http ://www.torry.net/authorsmore.php?id=2386 我使用了多年。
它也带有漂亮的人字形位图。
小问题:它不支持复合控件(如 TLabeledEdit)。
优点:该组件以单个 PAS 文件的形式提供(易于安装到 Palette 中)。他们说它适用于 Delphi 5,但我将它安装在 XE7 中并且可以正常工作(这表明质量)。
免费软件

TSplitView
如果您有较新版本的 Delphi(如 Tokyo),您可以使用 TSplitView。注意:它缺少 Align 属性。一开始它似乎只能与左对齐。但事实并非如此。它有一个 Placement 属性,而不是 Align 属性(具有两个值:svpRight / svpLeft)。
注意:它有一些与控件大小/位置相关的小故障。
注意:它不像 FoldingPanel 那样完整(甚至还没有)。您仍然需要编写一些代码来实现某种雪佛龙来折叠/展开面板。
https://www.youtube.com/watch?v=3hUG8o7PpCU
免费软件(如果您有 Delphi Tokyo)。

TCategoryPanelGroup
另请查看 TCategoryPanelGroup。它可能会或可能不会起作用,这取决于您需要它的用途。
免费软件(如果你有 Delphi XE7)

于 2018-12-12T10:05:17.730 回答