Многие из моих форм приложений наследуются от базовой формы, которая загружает сохраненный размер окна, положение и состояние, записанные во время 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, есть ли какой-либо другой способ настроить форму так, чтобы она была развернута без фактического отображения формы?
Вы не должны вызывать свою LoadFromState
процедуру ни из TBaseForm.FormShow
, ни из TBaseForm.FormActivate
.
TBaseForm.FormShow
вызывается каждый раз, когда видимость вашей формы меняется с False
на True
.
Так, например, если вы скроете свою форму при отображении другой, а затем снова покажете ее после закрытия другой формы, сработает TBaseForm.FormShow
, и, таким образом, вы загрузите размеры и положение формы из сохраненного состояния, которое может не совпадать с состоянием, когда форма была скрытый. Пользователь мог переместить и изменить размер с момента запуска приложения.
Это приведет к тому, что форма изменит свою позицию без желания пользователей, и, таким образом, это будет чертовски раздражать ваших пользователей.
Также не используйте TBaseForm.FormActivate
, так как это срабатывает каждый раз, когда Form получает фокус. Таким образом, изменение фокуса с другого на этот приведет к TBaseForm.FormActivate
и, таким образом, изменит размеры и положение вашей формы на сохраненное состояние, которое может не быть состоянием, когда форма потеряла фокус.
Правильное место для вызова вашей процедуры LoadFormState
, с помощью которой вы загружаете начальные свойства вашей формы, находится в конструкторе форм.
То же самое можно сказать и об использовании FormShow, поскольку его также можно вызывать несколько раз во время выполнения вашего приложения.
Понятия не имею, о чем ты говоришь. Да. FormShow можно вызывать несколько раз, но только в том случае, если пользователь закрывает и снова открывает форму, и, поскольку я сохраняю состояние формы при закрытии, при повторном открытии форма перезагружает размеры и положение, как это было при закрытии, так что да, состояние всегда одно и то же. Поскольку мои формы никогда не скрываются, а только уничтожаются, событие FormShow не может выполняться более одного раза для любого данного экземпляра формы, поэтому мой LoadFormState является последним фрагментом кода в событии FormShow. FormShow не запускается, если вы сворачиваете/разворачиваете форму, а затем восстанавливаете ее.
Я согласен с тем, что использование FormActivate, вероятно, потребует некоторой логики, чтобы указать, что при первом запуске он может загрузить состояние формы, но последующие запуски ничего не должны делать. Не беспокоюсь о FormShow, так как я никогда не использую FormHide. В конце концов я закодировал LoadFormState в конце события FormShow для каждой дочерней формы, которая в нем нуждалась.