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;

请注意,只要启动或离开用于移动/调整大小的辅助消息循环,就会发送消息 - 无法区分移动和调整大小。如果您需要确保仅捕获大小,则应在处理程序中比较框架的旧大小和新大小。

于 2009-12-04T08:10:03.697 回答
0

您可以尝试以下实现。

- 钩住所有者表单的 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 回答
0

1)用特殊的接口标记你的框架。喜欢:INeedLayoutAfterResize :)

2)编写 TForm 的自定义后代,它将捕获调整大小事件(如前面的答案所示),然后查找其子项,如果标记了某个子项,则重新布局其内容。

实际上我使用这种方法来保存和恢复控件状态。我的自定义迭代其子控件并查找 Tag 属性,如果它小于零,则将其状态写入 ini 文件。

于 2009-12-14T11:52:48.453 回答
0

我认为这可以通过调整大小事件停止(以重置时间)并启动具有等短超时(如 0,3 秒)的计时器来完成。然后框架的大小调整将在其余调整大小后不久完成。

于 2009-12-04T08:27:28.860 回答