Вопрос

В качестве расширения этот вопрос:

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

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

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

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

Это было полезно?

Решение

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

Другие советы

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

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

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

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

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

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

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

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

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

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

Во второй форме добавьте свойство и небольшой код регистрации в событие 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 в раздел Uses и поместите в форму кнопку и заметку.

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

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;

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top