2

内にいくつかのコントロール(つまり、TDBChart)がありTFlowPanelます。flow panelユーザーがそれらの1つをクリックすると、のクライアント領域全体が埋められるようにしたいと思います。ただし、実行時に子コントロールのvisibleandプロパティを変更しても効果はないようです。これに特別なトリックはありますか?メソッドを見つけましたが、コントロールのレイアウトには影響がないようです。これが私のイベントのコードです:alignflow panelRealign()OnClick

var
  AChart: TDBChart;
  V: Boolean;
  i: Integer;
begin
  AChart := TDBChart(Sender);
  if AChart.Align = alNone then
  begin
    V := False;
    AChart.Align := alClient;
  end else begin
    V := True;
    AChart.Align := alNone;
  end;
  for i := 0 to FlowPanel1.ControlCount - 1 do
    if FlowPanel1.Controls[i] is TDBChart then
      if FlowPanel1.Controls[i] <> AChart then
        FlowPanel1.Controls[i].Visible := V;
end;

チャートは期待どおりに非表示または表示されますが、のクライアント領域ADBChart全体を埋めることはありません。flow panel

4

2 に答える 2

3

設計上、T(Custom)FlowPanelオーバーライドされたメソッドで実装される、子コントロールのカスタマイズされた配置を使用しますAlignControls

このデフォルトの動作をスキップして、その祖先からフォールバックすることで、このデフォルトの動作を防ぐことができます。また、隣接するすべてのコントロールを非表示にする必要はありません。クリックしたチャートを前面に表示するだけで十分です。

type
  TFlowPanel = class(Vcl.ExtCtrls.TFlowPanel)
  private
    FFlowDisabled: Boolean;
    procedure SetFlowDisabled(Value: Boolean);
  protected
    procedure AlignControls(AControl: TControl; var Rect: TRect); override;
  public
    property FlowDisabled: Boolean read FFlowDisabled write SetFlowDisabled;
  end;

...

{ TFlowPanel }

type
  TWinControlAccess = class(TWinControl);
  TAlignControls = procedure(Instance: TObject; AControl: TControl;
    var Rect: TRect);

procedure TFlowPanel.AlignControls(AControl: TControl; var Rect: TRect);
begin
  if FFlowDisabled then
    // Skip inherited in TCustomFlowPanel:
    TAlignControls(@TWinControlAccess.AlignControls)(Self, AControl, Rect)
  else
    inherited;
end;

procedure TFlowPanel.SetFlowDisabled(Value: Boolean);
begin
  if FFlowDisabled <> Value then
  begin
    FFlowDisabled := Value;
    Realign;
  end;
end;    

{ TForm1 }

procedure TForm1.DBChartClick(Sender: TObject);
const
  FlowAligns: array[Boolean] of TAlign = (alNone, alClient);
var
  Chart: TDBChart;
  Panel: TFlowPanel;
  DisableFlow: Boolean;
begin
  Chart := TDBChart(Sender);
  Panel := Chart.Parent as TFlowPanel;
  DisableFlow := not Panel.FlowDisabled;
  Chart.Align := FlowAligns[DisableFlow];
  Chart.BringToFront;
  Panel.FlowDisabled := DisableFlow;
end;
于 2012-09-19T15:51:22.343 に答える
2

FlowPanelは、コントロールの位置を気にしないのと同じように、コントロールの配置設定を気にしません。フローするように設計されています。

1つの解決策は、新しいクラスを派生させてオーバーライドAlignControlsし、それに応じてサーフェスを埋めるコントロールのサイズを変更することです。例として:

type
  TFlowPanel = class(extctrls.TFlowPanel)
  protected
    procedure AlignControls(AControl: TControl; var Rect: TRect); override;
  end;

..

procedure TFlowPanel.AlignControls(AControl: TControl; var Rect: TRect);
var
  i, VisibleCount, VisibleControl: Integer;
begin
  VisibleCount := 0;
  VisibleControl := 0;
  for i := 0 to ControlCount - 1 do
    if Controls[i].Visible then begin
      Inc(VisibleCount);
      VisibleControl := i;
    end;

  if (VisibleCount = 1) and (Controls[VisibleControl] = AControl) and
      (AControl.Align = alClient) then begin
    // preserve 'Explicit..' settings
    AControl.ControlState := AControl.ControlState + [csAligning];
    AControl.SetBounds(1, 1, ClientWidth - 1, ClientHeight -1);
    AControl.ControlState := AControl.ControlState - [csAligning];
  end;

  inherited;
end;

次に、すべてのチャートのクリックイベントをこのハンドラーに設定できます。

var
  AChart: TTDBChart;

  procedure SetVisibility(Visible: Boolean);
  var
    i: Integer;
  begin
    for i := 0 to FlowPanel1.ControlCount - 1 do
      if FlowPanel1.Controls[i] is TDBChart then
        if FlowPanel1.Controls[i] <> AChart then
          FlowPanel1.Controls[i].Visible := Visible;
  end;

begin
  AChart := TDBChart(Sender);
  if AChart.Align = alNone then
  begin
    SetVisibility(False);
    AChart.Align := alClient;
  end else begin
    AChart.Align := alNone; // set before changing visible
    SetVisibility(True);
    AChart.SetBounds(0, 0, AChart.ExplicitWidth, AChart.ExplicitHeight);
  end;
end;

これは、固定サイズのフローパネルにのみ適していることに注意してください。

于 2012-09-19T15:07:25.140 に答える