В мире разработки программного обеспечения на Delphi часто возникает задача управления положением окон приложения. По умолчанию, новые формы могут появляться на первом мониторе или даже за пределами видимой области, что неудобно для пользователя. В этой статье мы рассмотрим, как настроить положение формы по умолчанию и сохранить его между запусками приложения, чтобы обеспечить более комфортный пользовательский опыт.
Проблема:
При каждом запуске приложения формы отображаются в предопределенном месте, игнорируя предыдущее расположение. Это может быть особенно неприятно, если пользователь работает с несколькими мониторами или часто меняет конфигурацию рабочего стола. Необходимо найти способ запоминать и восстанавливать положение формы при каждом запуске приложения.
Решение 1: Использование Ini-файла для сохранения и восстановления положения формы
Одним из наиболее распространенных и надежных способов является использование Ini-файла для хранения информации о положении и размере формы. Этот метод позволяет сохранять данные между сеансами работы приложения.
uses
System.IniFiles, Winapi.Messages;
const
INIFILE_NAME = 'MyApp.ini'; // Имя INI-файла
INISECTION_WINDOW = 'Window'; // Секция в INI-файле
INI_IDENT_LEFT = 'Left'; // Ключ для X-координаты
INI_IDENT_TOP = 'Top'; // Ключ для Y-координаты
INI_IDENT_WIDTH = 'Width'; // Ключ для ширины
INI_IDENT_HEIGHT = 'Height'; // Ключ для высоты
INI_IDENT_MAXIMIZED = 'Maximized'; // Ключ для состояния "Развернуто"
type
TMainForm = class(TForm)
private
FNormalX, FNormalY, FNormalW, FNormalH: Integer;
procedure WMSyscommand(var Msg: TWmSysCommand); message WM_SYSCOMMAND;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
protected
procedure LoadSettings; virtual;
procedure SaveSettings; virtual;
end;
implementation
{$R *.dfm}
procedure TMainForm.FormCreate(Sender: TObject);
begin
LoadSettings;
end;
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SaveSettings;
end;
procedure TMainForm.LoadSettings;
var
Ini: TIniFile;
begin
Ini := TIniFile.Create(ExtractFilePath(Application.ExeName) + INIFILE_NAME);
try
// Размер
Width := Ini.ReadInteger(INISECTION_WINDOW, INI_IDENT_WIDTH, Width);
Height := Ini.ReadInteger(INISECTION_WINDOW, INI_IDENT_HEIGHT, Height);
FNormalW := Width;
FNormalH := Height;
// Позиция (читаем после размера, чтобы центрирование работало корректно)
Left := Ini.ReadInteger(INISECTION_WINDOW, INI_IDENT_LEFT, Left);
Top := Ini.ReadInteger(INISECTION_WINDOW, INI_IDENT_TOP, Top);
FNormalX := Left;
FNormalY := Top;
// Состояние "Развернуто"?
if Ini.ReadBool(INISECTION_WINDOW, INI_IDENT_MAXIMIZED, False) then
WindowState := wsMaximized;
finally
Ini.Free;
end;
end;
procedure TMainForm.SaveSettings;
var
Ini: TIniFile;
begin
Ini := TIniFile.Create(ExtractFilePath(Application.ExeName) + INIFILE_NAME);
try
// Состояние "Развернуто"?
Ini.WriteBool(INISECTION_WINDOW, INI_IDENT_MAXIMIZED, WindowState = wsMaximized);
// Позиция и размер
if WindowState <> wsNormal then
begin
Ini.WriteInteger(INISECTION_WINDOW, INI_IDENT_LEFT, FNormalX);
Ini.WriteInteger(INISECTION_WINDOW, INI_IDENT_TOP, FNormalY);
Ini.WriteInteger(INISECTION_WINDOW, INI_IDENT_WIDTH, FNormalW);
Ini.WriteInteger(INISECTION_WINDOW, INI_IDENT_HEIGHT, FNormalH);
end
else
begin
Ini.WriteInteger(INISECTION_WINDOW, INI_IDENT_LEFT, Left);
Ini.WriteInteger(INISECTION_WINDOW, INI_IDENT_TOP, Top);
Ini.WriteInteger(INISECTION_WINDOW, INI_IDENT_WIDTH, Width);
Ini.WriteInteger(INISECTION_WINDOW, INI_IDENT_HEIGHT, Height);
end;
finally
Ini.Free;
end;
end;
procedure TMainForm.WMSyscommand(var Msg: TWmSysCommand);
begin
// Запоминаем нормальные X/Y/W/H перед максимизацией/минимизацией
if (msg.CmdType and $FFF0) = SC_MAXIMIZE then
begin
FNormalX := Left;
FNormalY := Top;
FNormalW := Width;
FNormalH := Height;
end;
inherited;
end;
end.
Пояснения к коду:
Использование TIniFile: Класс TIniFile позволяет легко читать и записывать данные в INI-файл.
Константы:INIFILE_NAME, INISECTION_WINDOW и INI_IDENT_* определяют имя файла, секцию и ключи для хранения данных.
LoadSettings: Загружает из INI-файла сохраненные значения Left, Top, Width, Height и WindowState и устанавливает их для формы.
SaveSettings: Сохраняет текущие значения Left, Top, Width, Height и WindowState в INI-файл.
Обработчики событий FormCreate и FormClose: Вызывают LoadSettings при создании формы и SaveSettings при закрытии формы.
Обработчик WMSyscommand: Перехватывает системные команды, такие как максимизация окна, и сохраняет текущие размеры и положение окна перед изменением состояния. Это необходимо для корректного восстановления положения окна после выхода из полноэкранного режима.
Переменные FNormalX, FNormalY, FNormalW, FNormalH: Используются для хранения нормального (не максимизированного) положения и размера окна.
Решение 2: Использование TForm.Position и TCustomForm.DefaultMonitor
Delphi предоставляет свойства TForm.Position и TCustomForm.DefaultMonitor для управления автоматическим размещением формы.
TForm.Position: Определяет, как форма будет размещена на экране. Возможные значения:
poDesigned: Форма будет размещена в соответствии с координатами, указанными в дизайнере.
poDefault: Форма будет размещена операционной системой.
poDefaultPosOnly: Операционная система определит только положение формы, а размер будет взят из дизайнера.
poDefaultSizeOnly: Операционная система определит только размер формы, а положение будет взято из дизайнера.
poScreenCenter: Форма будет отцентрирована на экране.
poDesktopCenter: Форма будет отцентрирована на рабочем столе.
TCustomForm.DefaultMonitor: Определяет, на каком мониторе будет отображаться форма. Возможные значения:
dmDesktop: Форма будет отображаться на мониторе, на котором находится большая часть формы.
dmPrimary: Форма будет отображаться на основном мониторе.
dmSecondary: Форма будет отображаться на вторичном мониторе (если он есть).
dmActiveForm: Форма будет отображаться на мониторе, на котором находится активная форма.
Пример:
В дизайнере формы установите свойство Position в poDesigned.
Переместите форму в желаемое положение на экране и установите нужный размер. Значения Left и Top будут автоматически обновлены.
При необходимости, установите свойство DefaultMonitor в нужное значение.
Этот метод хорош для установки фиксированного положения формы, но не позволяет сохранять положение между запусками приложения. Для этого необходимо комбинировать его с сохранением координат в INI-файл или другом хранилище.
Альтернативное решение: Использование реестра Windows
Вместо INI-файла можно использовать реестр Windows для хранения информации о положении формы. Этот метод может быть более подходящим для приложений, требующих более высокой степени защиты данных. Однако, работа с реестром требует большей осторожности и может быть более сложной для начинающих разработчиков.
Обработка ситуаций с изменением конфигурации мониторов
Как было отмечено в комментариях к вопросу, необходимо учитывать возможность изменения конфигурации мониторов. Например, пользователь мог использовать три монитора при закрытии приложения, а при следующем запуске у него остался только один. В этом случае, сохраненные координаты могут оказаться за пределами видимой области.
Для решения этой проблемы необходимо проверять, находятся ли сохраненные координаты в пределах доступной области экрана. Если координаты выходят за пределы, можно переместить форму в центр экрана или на основной монитор.
uses
System.IniFiles, Vcl.Forms, Vcl.Graphics;
procedure TMainForm.LoadSettings;
var
Ini: TIniFile;
ScreenRect: TRect;
begin
Ini := TIniFile.Create(ExtractFilePath(Application.ExeName) + INIFILE_NAME);
try
Left := Ini.ReadInteger(INISECTION_WINDOW, INI_IDENT_LEFT, Left);
Top := Ini.ReadInteger(INISECTION_WINDOW, INI_IDENT_TOP, Top);
Width := Ini.ReadInteger(INISECTION_WINDOW, INI_IDENT_WIDTH, Width);
Height := Ini.ReadInteger(INISECTION_WINDOW, INI_IDENT_HEIGHT, Height);
// Проверяем, находится ли форма в пределах экрана
ScreenRect := Screen.PrimaryMonitor.WorkareaRect;
if (Left < ScreenRect.Left) or (Left + Width > ScreenRect.Right) or
(Top < ScreenRect.Top) or (Top + Height > ScreenRect.Bottom) then
begin
// Если форма выходит за пределы экрана, перемещаем ее в центр
Left := (ScreenRect.Width - Width) div 2;
Top := (ScreenRect.Height - Height) div 2;
end;
finally
Ini.Free;
end;
end;
Заключение
Сохранение и восстановление положения формы между запусками приложения значительно улучшает удобство использования программы. Использование INI-файла является простым и эффективным способом решения этой задачи. Не забудьте учесть возможность изменения конфигурации мониторов и предусмотреть обработку ситуаций, когда сохраненные координаты оказываются за пределами видимой области. Также, не стоит забывать про свойства TForm.Position и TCustomForm.DefaultMonitor, которые могут упростить настройку положения формы по умолчанию. Выбор конкретного решения зависит от требований вашего приложения и личных предпочтений.
В статье рассматриваются способы установки положения формы по умолчанию в Delphi и сохранения его между запусками приложения, включая использование INI-файлов, свойств TForm.Position и TCustomForm.DefaultMonitor, а также обработку изменений в конфигураци
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.