1

アプリケーションの真ん中にフレームがあります。サイズ変更後、このパネルのコントロールを再配置する必要があります (サイズ変更イベントでこれを行うのはビジーです)。これがすべてのサイズ変更後に一度実行できると、より便利です。しかし、どのように?

ご協力ありがとうございました

4

4 に答える 4

2

秘訣は、親フォームのメッセージ処理にフックすることです(概念実証コード、Delphi 2009でテスト済み、エラーとコーナーケースの処理にはさらに作業が必要です)。

type
  TFrame2 = class(TFrame)
  strict private
    fOnEnterSizeMove: TNotifyEvent;
    fOnExitSizeMove: TNotifyEvent;
    fSavedWndProc: TWndMethod;
    procedure DoEnterSizeMove;
    procedure DoExitSizeMove;
    procedure ParentWindowProc(var AMessage: TMessage);
  protected
    procedure CreateWnd; override;
    procedure DestroyWnd; override;
  published
    property OnEnterSizeMove: TNotifyEvent read fOnEnterSizeMove
      write fOnEnterSizeMove;
    property OnExitSizeMove: TNotifyEvent read fOnExitSizeMove
      write fOnExitSizeMove;
  end;

{ TFrame2 }

procedure TFrame2.CreateWnd;
var
  ParentForm: TCustomForm;
begin
  inherited;
  ParentForm := GetParentForm(Self);
  if ParentForm <> nil then begin
    fSavedWndProc := ParentForm.WindowProc;
    ParentForm.WindowProc := ParentWindowProc;
  end;
end;

procedure TFrame2.DestroyWnd;
var
  ParentForm: TCustomForm;
begin
  ParentForm := GetParentForm(Self);
  if ParentForm <> nil then
    ParentForm.WindowProc := fSavedWndProc;
  inherited;
end;

procedure TFrame2.DoEnterSizeMove;
begin
  if Assigned(fOnEnterSizeMove) then
    fOnEnterSizeMove(Self);
end;

procedure TFrame2.DoExitSizeMove;
begin
  if Assigned(fOnExitSizeMove) then
    fOnExitSizeMove(Self);
end;

procedure TFrame2.ParentWindowProc(var AMessage: TMessage);
begin
  fSavedWndProc(AMessage);
  if AMessage.Msg = WM_ENTERSIZEMOVE then
    DoEnterSizeMove;
  if AMessage.Msg = WM_EXITSIZEMOVE then
    DoExitSizeMove;
end;

メッセージは、移動/サイジングの2次メッセージループが開始または終了するたびに送信されることに注意してください。移動とサイジングを区別する方法はありません。サイジングのみをキャッチする必要がある場合は、ハンドラーでフレームの新旧のサイズを比較する必要があります。

于 2009-12-04T08:10:03.697 に答える
0

サイズ変更イベントを停止して(時間をリセットするため)、短いタイムアウト(0,3秒程度)でタイマーを開始することで実行できると思います。次に、フレームのサイズ変更は、残りのサイズ変更の直後に行われます。

于 2009-12-04T08:27:28.860 に答える
0

1) フレームを特別なインターフェイス smth でマークします。のように: INeedLayoutAfterResize :)

2)サイズ変更イベントをキャプチャするTFormのカスタム子孫を記述し(以前の回答に示されているように)、その子を探し、子がマークされている場合はコンテンツを再レイアウトします。

実際、私はコントロールの状態を保存および復元するためにこのようなアプローチを使用しています。私のカスタムは、子コントロールを繰り返し処理し、Tag プロパティが 0 未満の場合は探し、その状態を ini ファイルに書き込みます。

于 2009-12-14T11:52:48.453 に答える
0

次の実装を試すことができます。

- 所有者フォームの on Resize イベントをフックし、フレーム内でそれを処理し、親の OnResize が持っていた可能性のあるイベント ハンドラーを起動します。

type
  TFrame2 = class(TFrame)
    Label1: TLabel;
    procedure FrameClick(Sender: TObject);
  private
    { Private declarations }
    FOnResize: TNotifyEvent;

    procedure OnFrameResize(Sender: TObject);
  public
    { Public declarations }
    // custom Frame constructor
    constructor Create(AOwner: TComponent); override;
  end;

implementation

{$R *.dfm}

{ TFrame2 }

constructor TFrame2.Create(AOwner: TComponent);
begin
  inherited;

  FOnResize := TForm(AOwner).OnResize;
  TForm(AOwner).OnResize := OnFrameResize;
end;

procedure TFrame2.OnFrameResize(Sender: TObject);
begin
  Label1.Caption := 'resize fired';
  if @FOnResize <> nil then
    FOnResize(Parent);
end;
于 2009-12-03T17:47:29.800 に答える