Установка WindowState показывает форму

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

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

Проблема, с которой я сталкиваюсь, заключается в том, что форма обычно скрыта до конца события FormShow потомка, что является ожидаемым поведением, если только для WindowState не установлено значение wsMaximized в событии FormShow класса-предка. В этом случае форма становится видимой, как только выполняется строка inherited;, и вы можете наблюдать, как организуются оставшиеся визуальные элементы.

При установке свойства WindowState для VCL.Forms.TForm выполняется следующий код:

procedure TCustomForm.SetWindowState(Value: TWindowState);
const
  ShowCommands: array[TWindowState] of Integer =
    (SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED);
begin
  if FWindowState <> Value then
  begin
    FWindowState := Value;
    if not (csDesigning in ComponentState) then
    begin
      if Showing then
        ShowWindow(Handle, ShowCommands[Value])
      else if HandleAllocated and (FWindowState = wsMaximized) then
        RecreateWnd;
    end;
  end;
end;

Очевидная причина проблемы кроется где-то в этом методе; либо ShowWindow, либо RecreateWnd, что, кажется, вызывает немедленную окраску формы.

Помимо перемещения моего метода LoadFormState(Self); из TBaseForm.FormShow в TBaseForm.FormActivate, есть ли какой-либо другой способ настроить форму так, чтобы она была развернута без фактического отображения формы?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
405
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не должны вызывать свою LoadFromState процедуру ни из TBaseForm.FormShow, ни из TBaseForm.FormActivate.

TBaseForm.FormShow вызывается каждый раз, когда видимость вашей формы меняется с False на True.
Так, например, если вы скроете свою форму при отображении другой, а затем снова покажете ее после закрытия другой формы, сработает TBaseForm.FormShow, и, таким образом, вы загрузите размеры и положение формы из сохраненного состояния, которое может не совпадать с состоянием, когда форма была скрытый. Пользователь мог переместить и изменить размер с момента запуска приложения.
Это приведет к тому, что форма изменит свою позицию без желания пользователей, и, таким образом, это будет чертовски раздражать ваших пользователей.

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

Правильное место для вызова вашей процедуры LoadFormState, с помощью которой вы загружаете начальные свойства вашей формы, находится в конструкторе форм.

Я согласен с тем, что использование FormActivate, вероятно, потребует некоторой логики, чтобы указать, что при первом запуске он может загрузить состояние формы, но последующие запуски ничего не должны делать. Не беспокоюсь о FormShow, так как я никогда не использую FormHide. В конце концов я закодировал LoadFormState в конце события FormShow для каждой дочерней формы, которая в нем нуждалась.

SiBrit 15.12.2020 22:23

То же самое можно сказать и об использовании FormShow, поскольку его также можно вызывать несколько раз во время выполнения вашего приложения.

SilverWarior 15.12.2020 22:28

Понятия не имею, о чем ты говоришь. Да. FormShow можно вызывать несколько раз, но только в том случае, если пользователь закрывает и снова открывает форму, и, поскольку я сохраняю состояние формы при закрытии, при повторном открытии форма перезагружает размеры и положение, как это было при закрытии, так что да, состояние всегда одно и то же. Поскольку мои формы никогда не скрываются, а только уничтожаются, событие FormShow не может выполняться более одного раза для любого данного экземпляра формы, поэтому мой LoadFormState является последним фрагментом кода в событии FormShow. FormShow не запускается, если вы сворачиваете/разворачиваете форму, а затем восстанавливаете ее.

SiBrit 16.12.2020 03:46

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