Перехват состояния окна, позиции и т. д. в Firemonkey

Я имею в виду удобство для пользователя, поэтому я хотел бы перехватить позицию каждой формы, которую я открываю, для сохранения и извлечения каждый раз, когда одна и та же форма открывается снова.

Поскольку я планирую портировать это для 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;

Я пытаюсь переместить форму на экране, но никакое событие не перехватывается. Я поставил точку останова в начале реализации метода, но ничего не происходит, пока я не закрою форму. В этом случае сообщение перехватывается.

Что я делаю не так?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, вы не переопределяете какой-либо уже существующий виртуальный метод, вы создаете свой собственный виртуальный метод, который ни к чему не привязан. Вот почему он никогда не вызывается.

Во-вторых, в отличие от 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, если они были ранее сохранены.

Другие вопросы по теме