Я имею в виду удобство для пользователя, поэтому я хотел бы перехватить позицию каждой формы, которую я открываю, для сохранения и извлечения каждый раз, когда одна и та же форма открывается снова.
Поскольку я планирую портировать это для MAC, я решил использовать FireMonkey.
К сожалению, нет события, которое запускается при перемещении формы на экране. Я попытался перехватить сообщение, которое должно быть запущено при перемещении, но поскольку ничего не происходит, я думаю, что формы Firemonkey не работают как формы VCL.
Я использую это объявление:
protected
procedure WndMethod(var Msg: TMessage); virtual;
и реализация этого метода
procedure TMYForm.WndMethod(var Msg : TMessage);
var
Handled: Boolean;
begin
// Assume we handle message
Handled := True;
case Msg.Msg of
WM_MOVE : begin
Edit_X.Text :='x - ' + MYForm.Left.ToString;
Edit_Y.Text :='y - ' + MYForm.Top.ToString;
end;
else
Handled := False;
end;
if Handled then
// We handled message - record in message result
Msg.Result := 0
else
// We didn't handle message
// pass to DefWindowProc and record result
Msg.Result := DefWindowProc(FHWnd, Msg.Msg,
Msg.WParam, Msg.LParam);
end;
Я пытаюсь переместить форму на экране, но никакое событие не перехватывается. Я поставил точку останова в начале реализации метода, но ничего не происходит, пока я не закрою форму. В этом случае сообщение перехватывается.
Что я делаю не так?
Во-первых, вы не переопределяете какой-либо уже существующий виртуальный метод, вы создаете свой собственный виртуальный метод, который ни к чему не привязан. Вот почему он никогда не вызывается.
Во-вторых, в отличие от VCL, FireMonkey не отправляет оконные сообщения виртуальному WndProc
методу, который вы можете переопределить, или любым message
обработчикам, которые вы можете определить в классе вашей формы. Несколько выбранных оконных сообщений обрабатываются только внутри (в частной WndProc()
функции внутри FMX.Platform.Win
модуля), они не выставляются на всеобщее обозрение. Любые необработанные сообщения (включая WM_MOVE
) удаляются.
Таким образом, в Windows единственный способ перехватить оконные сообщения в FireMonkey — это вызвать API Win32 SetWindowSubclass() или SetWindowLongPtr(GWLP_WNDPROC) , чтобы напрямую подключить базовый Win32 HWND
формы (см. MSDN для более подробной информации). Вы можете переопределить виртуальный CreateHandle()
метод формы для вызова API. Вы можете получить HWND
, вызвав функцию RTL Platform.Win.FormToHWND().
См. Как обнаружить кнопки мыши назад и вперед в форме Windows Delphi FMX? для примера такого подкласса.
Излишне говорить, что использование API Win32 не приведет к переносу на MacOS. Таким образом, вам придется использовать любой API для конкретной платформы, который MacOS предоставляет для перехвата окон. Я не знаю, как выглядит такой API. И в модуле FormToHWND()
нет такой функции, как FMX.Platform.Mac
, но есть функция WindowHandleToPlatform()
, которой вы можете передать Handle
формы. В MacOS WindowHandleToPlatform()
возвращает объект TMacWindowHandle
, содержащий свойства Wnd: NSWindow
, View: NSView
и Handle: TOCLocal
, которые можно использовать с собственными API MacOS.
При этом есть лучшая альтернатива — вам вообще не нужно напрямую подключать окно базовой платформы, вместо этого вы можете использовать функцию FireMonkey Save State . В событии OnSaveState
формы сохраните текущие значения Left
/Top
формы в свойстве формы SaveState по мере необходимости, а затем в событии OnCreate
формы вы можете восстановить значения из свойства SaveState
, если они были ранее сохранены.