如何实现TFrame的OnResizeEnd事件?

发布于 2024-08-13 12:38:17 字数 102 浏览 2 评论 0原文

应用程序的中间是一个框架。调整大小后,我需要重新排列此面板上的控件(在调整大小事件中执行此操作太忙)。 如果可以在所有调整大小之后执行一次,则更有用。但如何呢?

感谢您的帮助

in the middle of the application is a frame. After resizing i need to rearrange controls on this panel (doing this in the resizing event is too busy).
Its more useful if this can be done once after all the resizing. But how?

Thank you for your help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

许仙没带伞 2024-08-20 12:38:17

诀窍是挂钩父表单的消息处理(概念验证代码,使用 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;

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

The trick is to hook into message processing of the parent form (proof-of-concept code, tested with Delphi 2009, error and corner case handling need more work):

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;

Note that the messages are sent whenever a secondary message loop for moving / sizing has been started or left - there is no way to distinguish between moving and sizing. If you need to make sure that you catch sizing only, you should compare old and new size of the frame in the handler.

无所谓啦 2024-08-20 12:38:17

您可以尝试以下实现。

- 挂钩所有者窗体的 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;

You could try the following Implementation.

-Hook owner form's on Resize event, handle it within your frame, and Fire any Event Handler the parent OnResize Might have had.

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;
善良天后 2024-08-20 12:38:17

我认为这可以通过调整大小事件停止(重置时间)并启动一个带有短超时(如 0.3 秒)的计时器来完成。然后,帧的大小调整将在其余调整大小之后不久完成。

I think the it could be done by the resizing event stopping (to reset time) and starting a timer with et short timeout (lik 0,3 secs). Then the resize of the fram will be done shortly after the rest of the resizing.

泛泛之交 2024-08-20 12:38:17

1)用特殊接口标记您的框架。像: INeedLayoutAfterResize :)

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

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

1) Mark your frame with special interface smth. like: INeedLayoutAfterResize :)

2) Write custom descendant of TForm that would capture resize events (as shown in earlier answers), than looks for its children and if some child marked, than re-layout its content.

actually I use such approach for save and restore controls state.
my custom from iterate over its children controls and look for Tag property if it is less then zero, write its state to ini-file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文