2011-03-09 2 views
0

특정 VCL 컨트롤이 때때로 파괴되는 동안 이벤트를 실행하여 핸들러가 이미 파괴 된 하위 클래스 폼에서 호출되는 문제가 있습니다 (예 : 컨트롤이 소멸자에 의해 종료 됨).)파괴 중 VCL 이벤트

문제의 (타사) 컨트롤에 의한 계약 위반인가요? 모든 이벤트 처리기를 "if (open)"경비원으로 흩 뜨려야합니다. 이것은 다른 메커니즘에 의해 처리됩니다. 나는 __published 클로저가 자동으로 등록되지 않았을 것이라고 가정했으며, 정규 가상 함수의 작동 방식과 다소 유사하다고 생각했습니다.

답변

1

__published 클로저는 이러한 종류의 보증을하지 않으며, 클로저는 클래스 인스턴스와 함수 내의 포인터입니다. 그러나 VCL에는 다른 메커니즘이 있습니다.

일반적으로 다른 구성 요소에 종속 된 구성 요소를 개발할 때 구성 요소를 삭제할 때 내부 참조를 지우는 것이 좋습니다. VCL에서는 TComponent의 무료 알림을 통해이를 수행 할 수 있습니다.

당신이 의존하는 구성 요소가 다른 소유자이고 양식에없는 경우, 이러한 통지를 수신하기 위해 구성 요소를 등록해야합니다. FreeNotification 함수를 통해이 작업을 수행합니다 (이 경우). 알림을받은 구성 요소를 삭제할 때 구성 요소의 등록을 다시 취소해야합니다. 이 구성 요소와 동일한 양식 (또는 소유자)에 컨트롤이 추가 될 때마다 Notification 함수가 추가되거나 제거 된 구성 요소에 대한 참조와 함께 호출되어 수행됩니다.

Notification 함수를 덮어 쓰면 부모 함수도 호출해야합니다. 오버로드 된 기능은 다음과 같을 수 있습니다 :

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

    inherited::Notification(AComponent, Operation); 
} 

을이들은 물론 인해 부품이을 보장하고, dangling pointers가 있는지 확인해야합니다 타사 컨트롤들이 어떤 이유로 당신을 잊었을위한 경우, 해제되는 경우 서브 클래 싱하거나 명시된대로 이벤트를 재설정하여 해당 기능을 추가해야합니다. 이것이 당신 자신의 구성 요소라면, 반드시 이것을해야합니다.

2

컨트롤의 "소유자"속성이 올바로 설정되어 있습니까? 기본적으로 폼은 TForm 인스턴스를 가리키는 "소유자"속성을 가진 모든 컨트롤을 소유하며이 폼은 소유 된 모든 컨트롤을 해제합니다. 그것이 IDE 폼 디자이너를 통해 폼을 디자인하면 어떻게 작동하는지입니다. 수동으로 컨트롤을 만드는 경우에는 생성자를 통해 "Owner"속성을 제공해야합니다. 올바른 양식을 "소유자"로 전달했는지 확인하십시오. 또한 TControl 위에 구축 된 사용자 정의 컨트롤의 소스가있는 경우 해당 생성자가 기본 TControl 생성자에 "소유자"속성을 올바르게 전달하는지 확인하십시오.

+0

예, 이것은 실행 중 및 충돌 중일 때 양식에 대한 설계 및 소유자 속성 포인트에 의해 모두 자동으로 생성되었습니다. 레코드의 경우 예상 된 시간에 구성 요소가 손상된 것 같습니다. ~ TWinControl은 분명히 모든 소유 구성 요소를 통과하여 죽입니다. 문제가있는 컨트롤의 소멸자는 이미 파괴 된 이벤트를 폼에 전달하려고 시도합니다.이 이벤트는 그 시점에 부모 클래스가 남아 있습니다. – doynax

+0

소멸자에서 이벤트가 발생하는 이유는 무엇입니까? 어쨌든 이벤트 핸들러를 호출하기 전에 단순히 'csDestroying' 플래그의'ComponentState' 속성을 체크 할 수 있습니다. –