Событие VCL во время разрушения - PullRequest
0 голосов
/ 09 марта 2011

У меня проблема с тем, что некоторые элементы управления VCL иногда запускают события, будучи уничтоженными, вызывая вызовы обработчиков в подклассовой форме, которая уже была уничтожена (например, элемент управления уничтожается деструктором родителяthe TForm.)

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

Ответы [ 2 ]

2 голосов
/ 09 марта 2011

Правильно ли установлено свойство "Владелец" для ваших глючных элементов управления?По умолчанию форма владеет всеми находящимися в ней элементами управления, у которых свойство «Владелец» указывает на экземпляр TForm, и эта форма отвечает за освобождение всех принадлежащих элементов управления.Именно так все и работает, если вы разрабатываете свои формы с помощью IDE Form Designer.Если вы создаете элементы управления вручную, вы должны предоставить свойство «Владелец» через конструктор.Проверьте, правильно ли вы передали Форму как «Владелец».Кроме того, если у вас есть источники ваших пользовательских элементов управления, построенных на вершине TControl, проверьте, правильно ли их конструктор передает свойство «Владелец» базовому конструктору TControl.

1 голос
/ 09 марта 2011

__published замыкания не дают никаких гарантий такого рода, замыкание - это просто указатель на экземпляр класса и функцию внутри. Однако в VCL есть и другие механизмы, которые это делают.

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

Если компонент, на который вы полагаетесь, имеет другого владельца и отсутствует в форме, то вам необходимо зарегистрировать компонент, чтобы получать эти уведомления. Это делается с помощью функции FreeNotification (не забудьте снова отменить регистрацию компонента при удалении компонента, для которого используется уведомление, для этого используйте RemoveFreeNotification). Всякий раз, когда элемент управления добавляется в ту же форму (или владельца), что и этот компонент, вызывается функция Notification со ссылкой на добавленный или удаленный компонент и выполненное действие.

Таким образом, вы просто перезаписываете функцию Notification, не забудьте также вызвать функцию родителя. Перегруженная функция может выглядеть так:

void __fastcall TMyComponent::Notification(TComponent* AComponent, TOperation Operation)
{
    if (Operation == opRemove && AComponent == interestingComponent)
    {
        this->interestingComponent = NULL;
    }

    inherited::Notification(AComponent, Operation);
}

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

...