使用拆分器调整控件的大小超出父客户端区域

时间:2015-09-13 07:33:48

标签: delphi

我正在尝试使用分离器来复制调整大小,就像MS {{}}中描述的MS SQL Managment Studio一样。

所以我有一个ScrollBox,它有许多面板和分离器对,彼此垂直堆叠。当我想用相应的分离器放大面板时,它会限制可能的增长到滚动框中的剩余大小。我无法将分割器拖动到滚动框的客户端大小之外。

有没有人可以帮我解决这个问题?

我试图放大滚动框的VertScrollBar.Range,但没有成功:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  tDataBlock = class(TComponent)
    fPanel: TPanel;
    fLabel: TLabel;
    fSplitter: TSplitter;
    fOwner: TWinControl;
  published
    property Panel: TPanel    read fPanel   write fPanel;
    property Text: TLabel   read fLabel   write fLabel;
    property Owner: TWinControl read fOwner write fOwner;
  public
    constructor Create(Owner: TWinControl; var t: integer);
  end;

  TForm1 = class(TForm)
    ScrollBox1: TScrollBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    BlockCount: integer;
    procedure ConfigureScreen;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ConfigureScreen;
var i: integer;
    TotalHeight: integer;
begin
  TotalHeight := 0;
  for I := 0 to ScrollBox1.ComponentCount - 1 do begin
    if ScrollBox1.Components[i] is TPanel then
      TotalHeight := TotalHeight + TPanel(ScrollBox1.Components[i]).Height;
    if ScrollBox1.Components[i] is TSplitter then
      TotalHeight := TotalHeight + TSplitter(ScrollBox1.Components[i]).Height;
  end;
  ScrollBox1.VertScrollBar.Range := TotalHeight;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  I: Integer;
  db: tDataBlock;
  t: integer;
begin
  t := 0;
  BlockCount := 0;
  for I := 0 to 3 do begin
    db := tDataBlock.Create(ScrollBox1, t);
    Inc(BlockCount);
  end;
  ConfigureScreen;
end;

{ tDataBlock }

constructor tDataBlock.Create(Owner: TWinControl; var t: integer);
begin
  fOwner := Owner;

  fPanel := TPanel.Create(Owner);
  fPanel.Parent := Owner;
  fPanel.Height := 150;
  fPanel.Top := t;
  fPanel.Align := alTop;
  fPanel.AlignWithMargins := false;
  fPanel.Color := clRed;
  fPanel.ParentBackground := false;
  fPanel.BorderWidth := 0;
  fPanel.BorderStyle := bsNone;
  fPanel.Ctl3D := false;
  fPanel.AutoSize := false;
  fPanel.UseDockManager := false;
  t := fPanel.Top + Panel.Height + 1;

  fLabel := TLabel.Create(self);
  fLabel.Parent := fPanel;
  fLabel.Align := altop;
  fLabel.Caption := inttostr(fPanel.Height);
  fLabel.Font.Size := 10;

  fSplitter := TSplitter.Create(Owner);
  fSplitter.Parent:= Owner;
  fSplitter.Height := 3;
  fsplitter.Top := t;
  fSplitter.AutoSnap := false;
  fSplitter.AlignWithMargins := false;
  fSplitter.MinSize := 1;
  fSplitter.Align := alTop;

  t := fSplitter.Top + fSplitter.Height + 1;
end;

end.

1 个答案:

答案 0 :(得分:0)

正如SilverWarior所提到的,ClientRect的目的是划分客户区域,而不是将相邻控件调整为您想要的任何大小。为了实现您的目标,您需要通过NGLN建议的一些技巧来改变其行为。但是如果你这样做可能会遇到一些副作用,因为代码的其他部分可能需要TSplitter的ScrollBox。

其他选项是简单地使用鼠标事件来模拟TPanel的行为。我稍微更改了您的代码并改为使用unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls; type tDataBlock = class(TComponent) private fPanel: TPanel; fLabel: TLabel; fResizingPanel: TPanel; fOwner: TWinControl; IsResizing: Boolean; StartHeight, StartY: Integer; procedure ResizingPanelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure ResizingPanelMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure ResizingPanelMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); published property Panel: TPanel read fPanel write fPanel; property Text: TLabel read fLabel write fLabel; property Owner: TWinControl read fOwner write fOwner; public constructor Create(Owner: TWinControl; var t: Integer); end; TForm1 = class(TForm) ScrollBox1: TScrollBox; Button1: TButton; procedure Button1Click(Sender: TObject); private BlockCount: Integer; end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var I: Integer; db: tDataBlock; t: Integer; begin t := 0; BlockCount := 0; for I := 0 to 3 do begin db := tDataBlock.Create(ScrollBox1, t); Inc(BlockCount); end; end; { tDataBlock } constructor tDataBlock.Create(Owner: TWinControl; var t: Integer); begin fOwner := Owner; fPanel := TPanel.Create(Owner); fPanel.Parent := Owner; fPanel.Height := 150; fPanel.Top := t; fPanel.Align := alTop; fPanel.AlignWithMargins := False; fPanel.Color := clRed; fPanel.ParentBackground := False; fPanel.BorderWidth := 0; fPanel.BorderStyle := bsNone; fPanel.Ctl3D := False; fPanel.AutoSize := False; fPanel.UseDockManager := False; fPanel.Constraints.MinHeight := 50; // fPanel.DoubleBuffered := True; t := fPanel.Top + Panel.Height + 1; fLabel := TLabel.Create(self); fLabel.Parent := fPanel; fLabel.Align := alTop; fLabel.Caption := inttostr(fPanel.Height); fLabel.Font.Size := 10; fResizingPanel := TPanel.Create(Owner); fResizingPanel.Parent := Panel; fResizingPanel.Height := 10; fResizingPanel.Align := alBottom; fResizingPanel.AlignWithMargins := False; fResizingPanel.ParentBackground := False; fResizingPanel.Cursor := crVSplit; fResizingPanel.OnMouseDown := ResizingPanelMouseDown; fResizingPanel.OnMouseMove := ResizingPanelMouseMove; fResizingPanel.OnMouseUp := ResizingPanelMouseUp; t := fResizingPanel.Top + fResizingPanel.Height + 1; end; procedure tDataBlock.ResizingPanelMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin IsResizing := True; StartHeight := Panel.Height; StartY := fResizingPanel.ClientOrigin.Y + Y; end; procedure tDataBlock.ResizingPanelMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if IsResizing then Panel.Height := StartHeight + fResizingPanel.ClientOrigin.Y + Y - StartY; end; procedure tDataBlock.ResizingPanelMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin IsResizing := False; end; end. 。但这只是一个快速入门,您可能需要更多编码,例如删除闪烁;)。

{{1}}