Как реализовать событие OnResizeEnd для TFrame? - PullRequest
1 голос
/ 03 декабря 2009

в середине приложения находится рамка. После изменения размера мне нужно переставить элементы управления на этой панели (делать это в случае изменения размера слишком занят). Это более полезно, если это можно сделать один раз после изменения размера. Но как?

Спасибо за вашу помощь

Ответы [ 4 ]

2 голосов
/ 04 декабря 2009

Хитрость заключается в том, чтобы подключиться к обработке сообщений родительской формы (проверочный код, протестированный в 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;

Обратите внимание, что сообщения отправляются всякий раз, когда вторичный цикл сообщений для перемещения / изменения размера был запущен или оставлен - нет никакого способа различить перемещение и определение размера. Если вам нужно убедиться, что вы ловите только размер, вам нужно сравнить старый и новый размер кадра в обработчике.

0 голосов
/ 14 декабря 2009

1) Пометьте свой кадр специальным интерфейсом. как: INeedLayoutAfterResize:)

2) Напишите пользовательский потомок TForm, который будет записывать события изменения размера (как показано в более ранних ответах), чем ищет его дочерние элементы и, если какой-либо дочерний элемент помечен, чем изменить его содержимое.

на самом деле я использую такой подход для сохранения и восстановления состояния элементов управления. Мой обычай перебирать его дочерние элементы управления и искать свойство Tag, если оно меньше нуля, записывать его состояние в ini-файл.

0 голосов
/ 04 декабря 2009

Я думаю, что это можно сделать, остановив событие изменения размера (для сброса времени) и запустив таймер с кратким тайм-аутом (например, 0,3 с). Затем изменение размера будет выполнено вскоре после остального изменения размера.

0 голосов
/ 03 декабря 2009

Вы можете попробовать следующую реализацию.

-Записать форму владельца на событие 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;
...