Статья: Перехват и сохранение положения форм в Firemonkey для автоматического открытия в предыдущем положении
При разработке пользовательских интерфейсов часто возникает потребность сохранять и восстанавливать предыдущее положение форм для удобства пользователей. В этом материале мы рассмотрим, как это можно сделать в Firemonkey, учитывая особенности этой технологии и отсутствие событий, которые бы срабатывали при перемещении формы на экране.
Проблема
Разработчик хочет перехватывать положение каждой формы при открытии, чтобы сохранять и восстанавливать его при следующем открытии. Для портирования приложения на MAC было решено использовать Firemonkey. Однако, в отличие от VCL, Firemonkey не имеет события, которое бы срабатывало при перемещении формы на экране. Попытки перехватить сообщение, которое должно отправляться при перемещении, не увенчались успехом, что заставило разработчика предположить, что формы Firemonkey не работают так же, как формы VCL.
Ошибка в подходе
Первая ошибка заключается в том, что разработчик не переопределяетExisting virtual method, а создает свою собственную виртуальную метод, которая не подключена ни к чему. Именно поэтому она никогда не вызывается. Вторая ошибка связана с тем, что, в отличие от VCL, Firemonkey не отправляет сообщения окна в виртуальный метод WndProc или в обработчики сообщений, определенные на классе формы. Некоторые wenige select window messages are processed internally only (in a private WndProc() function inside the FMX.Platform.Win unit), they are not exposed publicly. Any unprocessed messages (including WM_MOVE) are discarded.
Решение
Для перехвата сообщений окна в Firemonkey на Windows можно использовать API Win32 SetWindowSubclass() или SetWindowLongPtr(GWLP_WNDPROC), чтобы напрямую подключиться к форме окна Win32 HWND (см. Subclassing Controls на MSDN для более подробной информации). Вы можете переопределить виртуальный метод CreateHandle() формы, чтобы вызвать API. Чтобы получить HWND, можно вызвать функцию RTL Platform.Win.FormToHWND().
Для MacOS придется использовать-platform-specific API, который экспонируется MacOS, чтобы подключиться к окнам. Необходимо использовать WindowHandleToPlatform() функцию, чтобы получить TMacWindowHandle объект, содержащий Wnd: NSWindow, View: NSView и Handle: TOCLocal свойства, которые можно использовать с родными API MacOS.
Однако, есть лучший альтернативный подход - использовать функцию сохранения состояния в Firemonkey. В событии OnSaveState формы можно сохранить текущие значения Left/Top в свойстве SaveState формы, а затем в событии OnCreate восстановить значения из свойства SaveState, если они были сохранены ранее.
Пример кода на Object Pascal (Delphi) для сохранения и восстановления положения формы:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
function GetFormState: TStrings;
procedure SetFormState(const Value: TStrings);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
SetFormState(GetFormState);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SetFormState(TStringList.Create);
end;
function TForm1.GetFormState: TStrings;
begin
Result := TStringList.Create;
Result.AddInt('Left', Left);
Result.AddInt('Top', Top);
end;
procedure TForm1.SetFormState(const Value: TStrings);
var
LeftValue, TopValue: Integer;
begin
if Value.Count = 2 then
begin
LeftValue := Value.Values['Left'].ToInteger;
TopValue := Value.Values['Top'].ToInteger;
Left := LeftValue;
Top := TopValue;
end;
Value.Free;
end;
end.
В этом примере, при создании формы, вызывается процедура SetFormState(), которая устанавливает положение формы из сохраненного состояния. При закрытии формы вызывается процедура GetFormState(), которая сохраняет текущее положение формы в свойстве SaveState. Таким образом, при следующем открытии формы, она будет открываться в предыдущем положении.
Статья описывает решение проблемы сохранения и восстановления положения форм в Firemonkey для автоматического открытия в предыдущем положении, учитывая отсутствие событий перемещения формы.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS