2010-01-13 1 views
0

나는 사용자 지정 구성 요소 (줄이기)연결된 델파이 컴포넌트 이벤트에 대한 응답

 TMyComponent = class(TComponent) 
public 
    procedure ClientConnected; 
published 
    property ClientSocket: TClientSocket Read ...etc 

바로 지금 ClientCocket OnConnect 이벤트 ClientConnected 예를 들어 있습니다.

 procedure TForm1.ElvinClient1Connect(Sender: TObject; Socket: TCustomWinSocket); 
begin 
    MyComponent1.ClientConnected; 
end; 

외부 이벤트가 필요없는 TMyComponent 클래스에서이를 수행 할 수있는 방법이 있습니까?

편집 :
ClientSocket이 런타임에 할당 된 구성 요소에 의해 생성되지 않는다는 사실을 잊어 버렸습니다.

개인 Proc

 procedure TMyComponent.OnClientConnected(sender: TObject); 
begin 
    ClientConnected; 
    if Assigned(oldOnClientConnected) then 
    oldOnClientConnected(sender); 
end; 

및 ClientSocket

 procedure TMyComponent.SetClientSocket(const Value: TClientSocket); 
begin 
    fClientSocket := Value; 
    oldOnClientConnected:= fClientSocket.OnElvinConnected; 
    fClientSocket.oldOnClientConnected:= OnClientConnected; 
end; 

에 대한 설정 도구를 가지고 시도했지만 그게 나를 돌아올 것 같은 느낌을받습니다 ...

답변

1

당신이 후크 할당 ClientSocket에 대한 이벤트를 성공적 필요가있는 무엇 (의 자식 요소를 부르 자)입니다 :

  • 정상 디자인 타임 동작을 "방해"하지 : 실행시에 자신의 이벤트 핸들러를 할당
  • 자식 구성 요소의 사용자 (개발자) 할당 이벤트 처리기를 저장하십시오.
  • 저장된 메서드를 안전하게 호출해야합니다.
  • 하위 구성 요소의 런타임 재 할당을 허용합니다. 물론

    TMyComponent = class(TComponent) 
    private 
        FClientSocket: TClientSocket; 
        FSavedClientConnected: TClientConnectedEvent; //Look for the Event type you want to save 
        procedure ClientConnected(AValidFirm: TFirm); //This method shall have a valid TClientConnectedEvent firm 
        procedure Hook;        //Set my own event handlers to the child component 
        procedure UnHook;        //Free the child component of my own event handlers ant let it as it was before 
    protected 
        procedure Loaded; override;     //Touch the child component after the container streaming load is finished 
        procedure Notification(AComponent: TComponent; Operation: TOperation); override; 
                   //Stay safe if the child component goes away 
    public 
        destructor Destroy; override;     //Cleanup the child component if I'm going away 
    published 
        property ClientSocket: TClientSocket read FClientSocket write SetClientSocket; 
                   //let's play 
    end; 
    
    procedure TMyComponent.SetClientSocket(Value: TClientSocket); 
    begin 
        if FClientSocket <> Value then 
        begin 
        UnHook; 
        FClientSocket := Value; 
        Hook; 
        end; 
    end; 
    
    procedure TMyComponent.Hook; 
    begin 
        if (csDesigning in ComponentState) or (csLoading in ComponentState) then Exit; 
        if Assigned(FClientSocket) then 
        begin 
        FSavedClientConnected := FClientSocket.SavedClientConnected; 
        FClientSocket.ClientConnected := ClientConnected; 
        end; 
    end; 
    
    procedure TMyComponent.UnHook; 
    begin 
        if Assigned(FClientSocket) then 
        begin 
        FClientSocket.ClientConnected := FSavedClientConnected; 
        FSavedClientConnected := nil; 
        end; 
    end; 
    
    procedure TMyComponent.Loaded; 
    begin 
        Hook; 
    end; 
    
    destructor TMyComponent.Destroy; 
    begin 
        UnHook; 
    end; 
    
    procedure TMyComponent.Notification(AComponent: TComponent; Operation: TOperation); 
    begin 
        if (AComponent = FClientSocket) and (Operation = opRemove) then 
        UnHook; 
        FClientSocket := nil; 
    end; 
    
    //the important part! 
    procedure TMyComponent.ClientConnected(AValidFirm: TFirm); 
    begin 
        DoMyOwnStuffWith(FClientSocket); 
        if Assigned(FSavedClientConnected) then 
        FSavedClientConnected(AValidFirm); 
        //as you see, you can call the saved event before, after or in the mid of your own stuff. 
    end; 
    

    , 그것은 컴파일되지 않습니다 (나는 확신 : 당신이 무대 뒤에서 무슨 일을하는지

  • 문서, 개발자의 무지가 엉망이 모든 것을
  • 예를 들어

수 있기 때문에 , 결코 시도하지 않았다). 그러나 그것은 단지 생각과 함께 간단하다. 어쩌면 내가 뭔가를 놓치고, 당신이 리뷰를 만들기 위해 실수를한다면 알려주세요.

+0

그 덕분에, 기본적으로 내가 뭘 시작,하지만 조금 더 생각 넣어 넣어 :) –

+0

도움이 듣기 좋은;) – jachguate

0

예, 구성 요소에 해당 서명이있는 프로 시저를 구현하고 TClientSocket을 구성 할 때 이벤트에 할당 할 수 있습니다.

... ClientSocket을 노출 했으므로 구성 요소를 사용하여 코드에서 이벤트 할당을 덮어 쓸 수 있음을 의미합니다. 일이 일어나는 순서와 구성 요소를 사용하게 될 사람에 따라 문제는 아닐 수도 있지만 ClientSocket을 비공개 또는 보호하거나 간단한 프록시를 작성하여 다음과 같이 사용할 수 있습니다. ClientConnected가 사용자의 이벤트 처리기보다 먼저 호출되는지 확인하십시오.

+0

이 말을 잊어 버렸지 만 ClientSocket은 아닙니다. 디자인 타임에 할당 된 구성 요소에 의해 만들어졌습니다. 나는 이것이 내가 어떻게하는지에 상관없이 지저분 해 보일 수도 있다고 생각한다. –

+0

이벤트를 "정시에"할당하는 한 할당 또는 생성 여부는 중요하지 않습니다.하지만 아닐 가능성은 적습니다. 개인적으로, 나는 그 프록시를 쓰는 것이 최선의 방법이라고 말하고 싶지만, 그것은 TClientSocket을 매우 빠르게 훑어 보는 것에 기반을두고 있으며, 당신의 정확한 요구에 의존 할 것입니다. 물론 컴포넌트 외부에서 제공되는 일반 TClientSocket 일 필요가있는 경우 현재 솔루션 이외의 다른 작업을 수행 할 수 있는지 실제로 알 수 없습니다. –

0

아마도 TClientSocket 클래스를 무시하고 이벤트가 호출되는 곳에서 자신의 루틴을 호출 할 수도 있습니다. 유일한 문제는이 오버라이드를 수행하기 위해 가상 또는 동적으로 표시된 루틴이 필요하며 TClientSocket이이를 수행하는지 검사하지 않았기 때문입니다.

이 경우에도 필요에 따라 클라이언트 소켓을 TClientsocket으로 노출 할 수 있습니다.