Я заметил что-то очень странное. Я сохраняю свойства верхней, левой, ширины и высоты формы при ее закрытии и используя эту информацию для восстановления последней позиции формы, когда она снова открывается, вызывая SetBounds с использованием ранее сохраненной информации. Это хорошо работает, но только в том случае, если свойство Position формы установлено в poDefault во время разработки. Если установлено что-то другое, например poDesigned, poScreenCenter или poMainFormCenter, SetBounds не восстанавливает предыдущую позицию и размер формы.Почему TForm.SetBounds работает правильно, когда TForm.Position установлен на poDefault во время разработки
Вот странная часть. Что, по-видимому, имеет значение, когда свойство Position задано во время разработки. Я могу изменить значение этого свойства во время выполнения до poDefault, и вызов SetBounds по-прежнему работает неправильно. Я пытался что-то вроде следующего
if Self.Position <> poDefault then
Self.Position := poDefault;
как в обработчике события OnCreate формы, а так же, как от перегруженной конструкторы (и установить позицию для poDefault в конструкторе, и называется SetBounds в OnCreate обработчик событий). Во всех случаях изменение свойства позиции формы на poDefault во время выполнения не устраняет проблему, которую я наблюдал с помощью SetBounds. Единственная последовательная модель, которую я нашел, заключается в том, что SetBounds работает так, как это должно быть, только если свойство позиции формы было poDefault во время разработки.
Есть другие вещи, которые я заметил в отношении того, как SetBounds работает, когда свойство позиции формы не установлено в poDefault во время разработки. Например, форма, чье свойство Position установлено в poScreenCenter во время разработки, не обязательно будет отображаться по центру на экране, если вы вызываете SetBounds. Однако он не отображается в верхнем левом местоположении, заданном SetBounds, и не учитывает ширину и высоту, указанные в вызове SetBounds. Позвольте мне повторить, однако, что я устанавливаю свойство Position формы в poDefault перед вызовом SetBounds. Я даже запустил вызов Application.ProcessMessages между двумя операциями, но это не устраняет проблему.
Я тестировал это с помощью Delphi 10.1 Berlin, работающего под Windows 10. Я также тестировал его с помощью Delphi XE6 в Windows 7. Те же результаты.
Если у вас есть сомнения, создайте приложение VCL с четырьмя формами. На первой форме разместить три кнопки, и добавить что-то вроде следующего OnClick для каждой кнопки:
with TForm2.Create(nil) do
try
ShowModal;
finally
Release;
end;
где конструктор создает TForm2, затем TForm3 и TForm4.
На OnCreate форм 2 до 4, добавьте следующий код:
if Self.Position <> poDefault then
Self.Position := poDefault;
Self.SetBounds(500,500,500,500);
На form2 установите позицию в poDefault, на Form3 задать положение для poScreenCenter, а form4 оставить позицию, установленную по умолчанию, poDefaultPosOnly. Только форма2 появится в 500, 500, с шириной 500 и высотой 500.
У кого-нибудь есть логическое объяснение этого результата?
Попробуйте добавить 'процедура CreateParams (var Params: TCreateParams); переопределить; 'в _protected_ раздел вашего определения формы и написать ' inherited; if Self.Position <> poDefault then Self.Position: = poDefault; 'in _CreateParams_. – Miamy
Miamy: Overridding CreateParams, и настройка Position to poDefault сработала !. Очень хорошо! Это не ответ (так как я просил объяснения), но это очень хорошее решение проблемы. И, поскольку у всех моих форм есть общий предок, я могу переопределить этот метод у предка, а затем можно бесплатно вызвать SetBounds в обработчике событий OnCreate (или переопределенном конструкторе). Спасибо за предложение. –