• 0
Viktor Chekrygin

Подписка на получение сообщений в конструкторах компонентов

Вопрос

Добрый день.

Только что обновился на Tokyo и сразу влетел на ошибку в компоненте TMediaPlayerControl. Этот компонент вообще не держится на форме в дизайнере и исчезает с формы при первом же клике мыши по форме. Саму ошибку я зарегистрировал в Embarcadero и дело собственно не в ней.

Разбираясь с этой проблемой, я обнаружил следующий непонятный текст в файле FMX.Media.pas:

constructor TMediaPlayerControl.Create(AOwner: TComponent);
begin
  inherited;
  TMessageManager.DefaultManager.SubscribeToMessage(TAfterCreateFormHandle, FormHandleAfterCreated);
  TMessageManager.DefaultManager.SubscribeToMessage(TBeforeDestroyFormHandle, FormHandleBeforeDestroyed);
end;
Здесь интересен метод FormHandleAfterCreated. Его текст такой:

procedure TMediaPlayerControl.FormHandleAfterCreated(const Sender: TObject; const Msg: TMessage);
begin
  if (FMediaPlayer <> nil) and (FMediaPlayer.FMedia <> nil) then
  begin
    if Sender is TForm then
      Parent := TForm(Sender);
  end;
end;
То есть, разработчики здесь через подписанный метод, ни много ни мало, пытаются инициализировать Parent компонента! Но странность здесь  в том, что этот метод никогда не будет вызван для компонента, так как сообщение TAfterCreateFormHandle генерится формой сразу после создания Handle формы, что собственно ясно даже из его названия (HandleAfterCreated). То есть, до того, как будут проинициализированы компоненты формы и вызваны их конструкторы с подпиской на этот класс. Следовательно и Parent компонента TMediPlayerControl в этом случае не будет проинициализирован.

Аналогичное использование подписки на TAfterCreateFormHandle я обнаружил и в компоненте TWebBrowser. То есть и там подписка из конструктора никогда не сработает, но тем не менее она и там есть!

Отсюда вопрос. А корректно ли вообще использовать подписки на TAfterCreateFormHandle в конструкторах компонентов? Или здесь есть какой-то скрытый смысл?

PS. Может быть дело в том, что разработчики компонент сами были введены в заблуждение следующими строками файла FMX.Forms.pas?

  /// <summary>Notification about creating real form</summary>
  TAfterCreateFormHandle = class(System.Messaging.TMessage<TCommonCustomForm>);

То есть, здесь в комментарии сказано, что класс TAfterCreateFormHandle это уведомление о создании формы, а не уведомление, о создании Handle формы, как следует даже из его названия.
 

Изменено пользователем Viktor Chekrygin

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

12 ответов на этот вопрос

  • 0

Не будем разбирать конкретно этот случай, пока Токио очень сырой.

Сломали всё что можно было. (обсуждали в чате)

Чтобы не плодить темы на форуме, вернитесь на Берлин апдейт 2, до какого нить хот-фикса от Ембы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

 

3 часа назад, Viktor Chekrygin сказал:

Notification about creating real form

Говорит, что уведомление о РЕАЛЬНОМ создании формы. Форма в обезьяне создается двумя фазами:

  1. Создание экземпляра формы и контролов
  2. Создание нативного хендла формы. Это и есть реальная физическая форма.

Это уведомление, как раз и сообщает, что есть уже у формы хендл и можно к нему подстроить браузер, проигрыватель и тд.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Не совсем так. Дело в том, что во время генерирования сообщения TAfterCreateFormHandle на форме ещё нет компонентов. То есть, сообщение есть, а подписок на этот класс ещё нет. Они будут позднее, на этапе размещения компонентов на форме. А выдаётся это сообщение только один раз, при создании Handle. Таким образом подписываться на него после этого в конструкторах компонентов нет никакого смысла. 

Было бы корректнее подписаться на сообщение TFormsCreatedMessage, то есть, после размещения всех компонентов на форме. В этом случае было бы всё так, как вы пишите. Форма с компонентами готова, подписки готовы, можно выдавать и сообщение. А сейчас всё наоборот получилось.

Изменено пользователем Viktor Chekrygin

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Раньше хендл пересоздавался несколько раз. Это приводит к повторной отправке сообщения. Но видимо в последних версиях это поломали.

Как вариант можно вызывать Recreate у формы, чтобы принудительно попробовать пересоздать хендл

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

А вообще у медиа проигрывателя родитель и так устанавливается. Но то, что родитель меняется - это явный баг. Там максимум хендл мог у окна браться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
5 часов назад, Равиль Зарипов (ZuBy) сказал:

Не будем разбирать конкретно этот случай, пока Токио очень сырой.

Сломали всё что можно было. (обсуждали в чате)

Чтобы не плодить темы на форуме, вернитесь на Берлин апдейт 2, до какого нить хот-фикса от Ембы.

Что ж вы такое интересное в чате обсуждаете, это же тема не на один час, и даже не на месяц. Могли бы и тему создать. Наверное потому что бот Ярослава постит и закрывает темы, так можно было в той же теме (Whats New in Tokyo) по обсуждать. @brovin-yaroslav это вам на заметку, большая просьба не закрывать темы-новости.

Изменено пользователем ENRGY

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
19 часов назад, Brovin Yaroslav сказал:

Раньше хендл пересоздавался несколько раз. Это приводит к повторной отправке сообщения. Но видимо в последних версиях это поломали.

Как вариант можно вызывать Recreate у формы, чтобы принудительно попробовать пересоздать хендл

Скорее всего так и было. Сначала изменили компонент TMediaPlayerControl, всё работало, затем что-то изменили в форме, а когда всё собрали в кучу, TMediaPlayerControl перестал работать.

Recreate помогает в плане того, что да, в realtime подписка по нему срабатывает. Если честно, мне вообще не понятен изначальный смысл Recreate. В каких случаях он может быть полезен, кроме как для аварийного исправления таких вот ошибок? Для чего может понадобиться менять Handle во время работы программы?

19 часов назад, Brovin Yaroslav сказал:

А вообще у медиа проигрывателя родитель и так устанавливается. Но то, что родитель меняется - это явный баг. Там максимум хендл мог у окна браться.

У TMediaPlayerControl дело не в родителе. Parent там указывает на форму. Но вот на форме компонент не держится и исчезает после первого клика. В Берлине же всё работает. В общем в Токио, чего-то там сломали. Так и не понял, в чём там дело.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Хендл может поменяться, когда вы меняете стиль формы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Ярослав, спасибо за ответ. Теперь буду знать. Может быть ответите ещё на один вопрос? В исходниках в полях классов я часто вижу такие конструкции:

[weak] FForm: TCommonCustomForm;

Как это можно объяснить? Для интерфейсов, всё понятно. Но для классов? Как это можно использовать? Понятно, что TCommonCustomForm интерфейсный класс. Но слабая ссылка на класс предполагает, что поле будет считаться классом, а не интерфейсом. Как-то не достаточно освещён этот вопрос. 

Изменено пользователем Viktor Chekrygin

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

на здоровье.

22 минуты назад, Viktor Chekrygin сказал:

Как это можно объяснить?

http://yaroslavbrovin.ru/object_life_cycle_in_delphi_part_2_android_ios-ru/

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Ну я в общем-то так и предполагал, что это для ARC для мобильных платформ сделано. В вашей статье информация по этой теме собрана воедино. Как раз этого лично мне не хватало. Спасибо огромное.

Brovin Yaroslav понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу