【问题标题】:How to implement the OnResizeEnd Event for TFrame?如何实现 TFrame 的 OnResizeEnd 事件?
【发布时间】:2010-12-22 21:26:27
【问题描述】:

在应用程序的中间是一个框架。调整大小后,我需要重新排列此面板上的控件(在调整大小事件中这样做太忙了)。 如果这可以在所有调整大小后完成一次,它会更有用。但是怎么做呢?

感谢您的帮助

【问题讨论】:

    标签: delphi onresize tframe


    【解决方案1】:

    您可以尝试以下实现。

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

    【讨论】:

    • 我认为他想延迟调整大小“(在调整大小事件中这样做太忙了)”。 PS。也可以通过在框架上放置一个面板来调整大小,其中包含所有组件。
    • OnResizeEnd 事件发生在 Paren'ts OnResize 调用之后。就在上面写着FOnResize(Parent) 的地方,你可以在那里插入任何代码来处理它
    【解决方案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;
    

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-11
          • 2013-12-29
          • 2011-04-28
          • 1970-01-01
          • 2012-11-27
          • 1970-01-01
          • 2015-12-10
          • 1970-01-01
          相关资源
          最近更新 更多