2

アンカーに小さな問題があります。

Panel1私は2 つのパネルを持つフォームを持っていPanel2ます。2 番目のパネルには 2 つの編集があり、左、右、および下のみに固定されています。この設計により、フォームのサイズが変更されると編集が上部に消える「最小化」スライド効果が発生します。これは意図されたものです。

アプリケーションの開始時に、2 番目のパネルの初期状態が非表示になっている必要があるため、 を使用しますPanel2.Height := 0

ただし、フォームのサイズを変更したり、手動で を設定したりした後Panel2.Height := 104、編集はアンカーされた位置までドラッグされず、パネルの外には表示されません。

これは、それを視覚化するのに役立つサンプル コードです。

// unit 1
unit Unit1;

interface

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

type
  TMoveEvent = procedure (Sender: TObject; X, Y: Integer) of object;

  TLabeledEdit = class(ExtCtrls.TLabeledEdit)
  private
    FOnMove: TMoveEvent;
    procedure WMMove(var Message: TWMMove); message WM_MOVE;
  public
    property OnMove: TMoveEvent read FOnMove write FOnMove;
  end;

  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    LabeledEdit1: TLabeledEdit;
    LabeledEdit2: TLabeledEdit;
    Button1: TButton;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    procedure LE1Move(Sender: TObject; X, Y: Integer);
    procedure LE2Move(Sender: TObject; X, Y: Integer);
  public
    procedure AfterConstruction; override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  TypInfo;

const
  MaxSet = 255; // Largest ordinal value in a Delphi set.

type
  TSet = set of 0..MaxSet;

function SetToString(Info: PTypeInfo; const Value; const Separator, Prefix, Suffix: string): String; overload;
var
  CompInfo: PTypeInfo;
  CompData: PTypeData;
  SetValue: TSet absolute Value;
  Element: 0..MaxSet;
begin
  CompInfo:=GetTypeData(Info)^.CompType^;
  CompData:=GetTypeData(CompInfo);
  Result:='';
  for Element:=CompData.MinValue to CompData.MaxValue do begin
    if Element in SetValue then
      if Result = '' then
        Result := Prefix + GetEnumName(CompInfo, Element)
      else
        Result := Result + Separator + GetEnumName(CompInfo, Element);
  end;
  if Result = '' then
    Result := Prefix + Suffix
  else
    Result := Result + Suffix;
end;

function SetToString(Info: PTypeInfo; const Value; const Separator: string): String; overload;
begin
  Result:=SetToString(Info, Value, Separator, '[', ']');
end;

function SetToString(Info: PTypeInfo; const Value): String; overload;
begin
  Result:=SetToString(Info, Value, ', ');
end;

{ TLabeledEdit }

procedure TLabeledEdit.WMMove(var Message: TWMMove);
begin
  inherited;
  if Assigned(FOnMove) then
    FOnMove(Self, Message.XPos, Message.YPos);
end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  LabeledEdit1.OnMove:=LE1Move;
  LabeledEdit2.OnMove:=LE2Move;
end;

procedure TForm1.AfterConstruction;
begin
  inherited;
  Panel2.Height:=0;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Panel2.Height:=0;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Panel2.Height:=104;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ShowMessage('LE1 Anchors = ' + SetToString(TypeInfo(TAnchors), LabeledEdit1.Anchors));
  ShowMessage('LE2 Anchors = ' + SetToString(TypeInfo(TAnchors), LabeledEdit2.Anchors));
end;

procedure TForm1.LE1Move(Sender: TObject; X, Y: Integer);
begin
  Label1.Caption:=Format('LE1 pos: %d : %d', [X, Y]);
end;

procedure TForm1.LE2Move(Sender: TObject; X, Y: Integer);
begin
  Label2.Caption:=Format('LE2 pos: %d : %d', [X, Y]);
end;

end.

// dfm
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 304
  ClientWidth = 643
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 200
    Top = 56
    Width = 31
    Height = 13
    Caption = 'Label1'
  end
  object Label2: TLabel
    Left = 200
    Top = 96
    Width = 31
    Height = 13
    Caption = 'Label2'
  end
  object Panel1: TPanel
    Left = 0
    Top = 0
    Width = 185
    Height = 304
    Align = alLeft
    TabOrder = 0
    ExplicitLeft = 152
    ExplicitTop = 96
    ExplicitHeight = 41
    DesignSize = (
      185
      304)
    object Panel2: TPanel
      Left = 1
      Top = 81
      Width = 183
      Height = 104
      Anchors = [akLeft, akTop, akRight, akBottom]
      Constraints.MaxHeight = 104
      TabOrder = 0
      DesignSize = (
        183
        104)
      object LabeledEdit1: TLabeledEdit
        Left = 8
        Top = 24
        Width = 121
        Height = 21
        Anchors = [akLeft, akRight, akBottom]
        EditLabel.Width = 61
        EditLabel.Height = 13
        EditLabel.Caption = 'LabeledEdit1'
        TabOrder = 0
      end
      object LabeledEdit2: TLabeledEdit
        Left = 48
        Top = 72
        Width = 121
        Height = 21
        Anchors = [akLeft, akRight, akBottom]
        EditLabel.Width = 61
        EditLabel.Height = 13
        EditLabel.Caption = 'LabeledEdit2'
        TabOrder = 1
      end
    end
  end
  object Button1: TButton
    Left = 200
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Hide'
    TabOrder = 1
    OnClick = Button1Click
  end
  object Button2: TButton
    Left = 281
    Top = 8
    Width = 75
    Height = 25
    Caption = 'Show'
    TabOrder = 2
    OnClick = Button2Click
  end
  object Button3: TButton
    Left = 200
    Top = 140
    Width = 75
    Height = 25
    Caption = 'Anchors'
    TabOrder = 3
    OnClick = Button3Click
  end
end

フォームの作成後に が 0 に設定されていない場合Panel2.Height、フォームのサイズが変更されたときに編集が上下に移動します。フォームの作成時に が 0 に設定されている場合Panel2.Height、編集内容は の外に表示されず、 が表示されているPanel2場合Panel2は表示されないため、Top位置が負になります。

誰でも助けることができますか?

4

3 に答える 3

3

固定されたコントロールは、実際に存在する場所に固定された位置を持つことを好みます。Delphi は、すべてが収まらないスペースにコントロールを配置するのに問題があります。アンカーが間違った位置で「動かなくなる」可能性があり、隣接する位置合わせされたコントロールが誤って互いに場所を交換する可能性があります。

コントロールが存在するパネルが正のサイズに変更されたら、コントロールの位置を調整して、配置したい場所に配置します。それらが表示されている限り (つまり、パネルがゼロの高さに折りたたまれていない限り)、それらのアンカーは適切な場所にそれらを保持し続けます。

于 2013-02-26T16:41:06.420 に答える
2

考えられる解決策は次の 2 つです。

  1. の代わりにフォームのイベントPanel2で の高さをゼロに設定する、またはOnShowAfterConstruction
  2. で別のパネルを配置Panel2Align=alBottomます。

最初のソリューションが機能する正確な理由はわかりませんが、使用中OnCreate(またはAfterConstruction使用中) にウィンドウ コントロール ハンドルがまだ割り当てられていないため、確かにメリットがあります。

于 2013-02-27T18:10:35.863 に答える
1

この問題の回避策を見つけましたが、アンカーとは関係ありません。もっと関係がありAlign = alCustomます...

しかし、私がそれをどのように解決したかに興味がある人は、それを説明するコードを次に示します。

// modified form create procedure
procedure TForm1.FormCreate(Sender: TObject);
begin
  LabeledEdit1.Align:=alCustom; // go to hell with automation
  LabeledEdit1.Anchors:=[akLeft, akRight, akBottom]; // this can be ommited
  LabeledEdit2.Align:=alCustom; // go to hell with automation
  LabeledEdit2.Anchors:=[akLeft, akRight, akBottom]; // this can be ommited
  LabeledEdit1.OnMove:=LE1Move;
  LabeledEdit2.OnMove:=LE2Move;
end;

を処理する必要がありOnAlignPositionますPanel2

type
  TUnProtectedWinControl = class(TWinControl);

procedure TForm1.Panel2AlignPosition(Sender: TWinControl; Control: TControl; var NewLeft, NewTop, NewWidth, NewHeight: Integer; var AlignRect: TRect; AlignInfo: TAlignInfo);
begin
  if (Sender <> Nil) and (Sender is TWinControl) then begin
    if Control.Parent <> Nil then begin
      if Control.ExplicitTop > 0 then
        NewTop:=Control.Parent.Height - (TUnProtectedWinControl(Sender).FDesignSize.Y - Control.ExplicitTop)
      else
        NewTop:=Control.Parent.Height + Control.ExplicitTop;
    end;
  end;
end;

それでおしまい。

于 2013-02-28T06:38:04.153 に答える