nesco писал(а):
Уже нашел и исправил.1) Поле CustomData автоматически освобождается по FreeMem(fCustomData) в деструкторе TControl.Destroy, а мы в него заносим THIMST_UseEditCtrl, который должен освобождаться по TObject(fCustomData).Free. Это приводит к падению при закрытии программы (на компиляторе Delphi не всегда заметно, поскольку, видимо, не успевает выдать сообщение об ошибке, на FPC - стабильно падает).
2) Компонент THIMST_UseEditCtrl создается и уничтожается автоматически. Поэтому такая цепочка могла бы приводить к падению при закрытии программы (но по причине первого пункта не выполняется):
- уничтожается ThiMTStrTbl
- в ThiWin.Destroy уничтожается контрол в поле Control
- TControl.Destroy уничтожает прописанное в CustomData, то-есть, наш THIMST_UseEditCtrl
- следующее автоматическое уничтожение THIMST_UseEditCtrl пытается уничтожить уже уничтоженный объект
Исправить можно, если в CustomData прописывать не Self, а созданную по GetMem переменную типа PPointer, в которую занести Self. Тогда FreeMem(fCustomData) освободит эту переменную, а THIMST_UseEditCtrl останется нетронутым.
3) Но это - тупиковый путь. ThiMTStrTbl тоже назначает свою оконную процедуру. Для доступа к самому себе из этой процедуры, он прописывает себя в Control.Tag. Как мы уже убедились, THIMST_UseEditCtrl тоже хочет добавить свою процедуру, а поскольку поле Control.Tag уже используется, то пришлось себя прописывать в CustomData. А если будет третий компонент, которому тоже нужно будет обрабатывать сообщения от этого Control? Куда он себя пропишет?
Это, видимо, является причиной вопроса и к ListEdit.pas.
НУЖНО:
- ловить сообщения от Control только в ThiMTStrTbl либо через AttachProc, либо по перекрытию ThiWin._onMessage.
- добавить в ThiMTStrTbl поле PList и пару методов SubscribeToMsg(MsgMethod: TOnMessage)/UnsubscribeFromMsg(MsgMethod: TOnMessage).
- каждый клиент к менеджеру ThiMTStrTbl, который хочет получать сообщения (например, наш THIMST_UseEditCtrl), вызывает SubscribeToMsg и указывает метод, который нужно вызывать при поступлении сообщения
- метод ThiMTStrTbl.SubscribeToMsg создает список подписчиков PList (если ещё не создан), и добавляет туда этот метод
- в процедуре обработки сообщений ThiMTStrTbl обрабатывает интересующие его сообщения, а потом пробегается по PList и передает сообщение всем подписавшимся обработчикам.
Поскольку такой подход может требоваться и в других компонентах, то, чтобы не повторять эти методы в каждом таком компоненте, это можно интегрировать прямо в ThiWin. Получается, если визуальный компонент наследует ThiWin, то к такому компоненту можно будет подписываться на сообщения без плясок с Control.Tag, Control.CustomData (потому, что они позволяют подписать только 2 компонента, ну и ещё наследник может перекрыть ThiWin._onMessage).
Дополнительный вопрос. Я не в курсе, как происходит процес уничтожения связки менеджер-клиент. То-есть, когда мы в клиенте указываем менеджера в свойстве _prop_MSTControl, клиент сохраняет ссылку на него у себя. Что будет (если такое возможно), если менеджер будет уничтожен раньше, чем клиент? Клиент ведь будет и дальше обращаться к несуществующему менеджеру.