При каких условиях TForm запускает OnResize на шоу? - PullRequest
4 голосов
/ 06 августа 2009

Как расширение этот вопрос :

TForm.OnResize иногда вызывается до того, как форма впервые показывается, но не всегда. Например, если BorderStyle имеет тип bsDialog или bsNone, OnResize не будет запускаться. Для всех других значений BorderStyle (и со всеми другими свойствами по умолчанию) OnResize срабатывает.

Существуют ли другие факторы, влияющие на то, будет ли OnResize срабатывать до отображения формы? Например, другие свойства или комбинации свойств, которые могут повлиять на это?

Событие OnResize является результатом функции API ShowWindow, отправляющей в окно сообщение WM_SIZE. Это повторяет: сообщение приходит из Windows, а не из Delphi. Это функция Windows (ShowWindow), которая (иногда) отправляет сообщение, которое вызывает событие - поэтому исходный код VCL не действительно полезно в этом случае.

Бонусные баллы за окончательные ответы, основанные на задокументированном поведении ShowWindow / WM_SIZE, например, ссылки на документацию MSDN или книги Petzold.

Ответы [ 3 ]

1 голос
/ 16 августа 2009

Возможно, это даже зависит от настроек дисплея пользователя, темы рабочего стола или версии Windows. Если бы OnResize давал мне такие проблемы, я бы строил свою программу так, чтобы она всегда ожидала этого и справлялась с ней в любой ситуации, независимо от того, что я считаю причиной.

0 голосов
/ 07 августа 2009

Там нет замены для тестирования. Как насчет создания формы в коде, установки интересующих вас свойств и записи при вызове события resize.

Если вы извините за уродство кода, вот грубое доказательство концепции, которая тестирует все комбинации BorderStyle и Position без явного кодирования для каждой. Вы можете добавить больше свойств и сделать это так, как вам нравится. Такой инструмент, как CodeSite, сделает ведение журналов чище и проще.

Создайте приложение с 2 формами. Убедитесь, что второй не создан автоматически.

Во второй форме добавьте свойство и добавьте небольшой код регистрации в событие Resize формы:

  private
    FOnResizeFired: TNotifyEvent;
  public
    property OnResizeFired: TNotifyEvent read FOnResizeFired write FOnResizeFired;
  end;

...

procedure TForm2.FormResize(Sender: TObject);
begin
  if Assigned(FOnResizeFired) then
    FOnResizeFired(self);
end;

В основной форме добавьте TypInfo к предложению использования и поместите кнопку и памятку в форму.

Добавить простую процедуру:

procedure TForm1.ResizeDetected(Sender: TObject);
begin
  Memo1.Lines.Add('    *** Resize detected');
end;

Теперь добавьте следующее к событию ButtonClick:

procedure TForm1.Button1Click(Sender: TObject);
var
  lBorderStyle: TFormBorderStyle;
  lBorderStyleName: string;
  lPosition: TPosition;
  lPositionName: string;
  lForm: TForm2;
begin
  Memo1.Clear;
  for lBorderStyle in [low(TFormBorderStyle) .. high(TFormBorderStyle)] do
  begin
    for lPosition in [low(TPosition) .. high(TPosition)] do
    begin
      lBorderStyleName := GetEnumName(TypeInfo(TFormBorderStyle), Integer(lBorderStyle));
      lPositionName := GetEnumName(TypeInfo(TPosition), Integer(lPosition));
      Memo1.Lines.Add(Format('Border: %s  Position: %s', [lBorderStyleName, lPositionName]));

      Memo1.Lines.Add('  Creating form');
      lForm := TForm2.Create(self);
      try
        Memo1.Lines.Add('  Form Created');
        lForm.OnResizeFired := ResizeDetected;
        Memo1.Lines.Add('    Setting border style');
        lForm.BorderStyle := lBorderStyle;
        Memo1.Lines.Add('    Setting Position');
        lForm.Position := lPosition;
        Memo1.Lines.Add('    Showing form');
        lForm.Show;
        Memo1.Lines.Add('    Form Shown');
        lForm.Close;
        Memo1.Lines.Add('    Form Closed');
      finally
        FreeAndNil(lForm);
        Memo1.Lines.Add('    Form Freed');
      end;
    end;
  end;
end;

Вы заметите, что изменение размера срабатывает, когда некоторые свойства устанавливаются до отображения формы, и я вижу, что в некоторых комбинациях изменение размера срабатывает дважды при отображении формы. Интересно.

0 голосов
/ 07 августа 2009

Я считаю, что OnResize сработает, когда событие отправит сообщение говоря, что размер формы (слева, снизу, ширина, высота) будет изменен.

Поскольку вы уже обнаружили, какое сообщение вызывает это событие, вам нужно Теперь проследите, куда сообщение отправляется в vcl.

Посмотрите на исходный код vcl, чтобы увидеть, можете ли вы обнаружить эти операции.

Редактировать: давайте перейдем на низкий уровень. Формы в окнах (грубо говоря) есть какие называется "класс окна" (это не класс, как мы знаем, что упс). Каждый раз, когда размер окна формы изменяется (и форма видима), WM_SIZE отправляется.

Таким образом, это не будет происходить при каждом показе формы, но только ее размеры будут изменены по сравнению с базовым классом окна.

Как вы заметили, многие свойства valuez изменяют размеры формы (даже несколько пикселей).

Это очень поверхностное объяснение, это тонна других деталей - но я понимаю, как все работает "под капотом".

...