2010-01-13 15 views
0

我有一個自定義組件(減少)應針對與德爾福組件活動

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

現在我有在ClientSocket的呼叫ClientConnected如的的onConnect事件

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

謝謝你,似乎基本上是我開始做的,但有更多的想法放在它:) – 2010-01-25 05:21:34

+0

好聽,它有幫助;) – jachguate 2010-01-26 03:32:28

0

是的,你可以在組件中實現一個帶有該簽名的過程,並在構造TClientSocket時將其分配給事件。但是,由於您公開了ClientSocket,這意味着可以使用您的組件從代碼中覆蓋該事件分配。取決於事情發生的順序以及誰將使用你的組件,這對你來說可能不是問題 - 但你可能想考慮使ClientSocket變得私有或受保護,或者可能寫一個簡單的代理,然後用它來確保您的ClientConnected在用戶的事件處理程序之前被調用。

+0

忘了說這個,但是ClientSocket不是由Component創建的,它在設計時被分配。我認爲這可能是混亂的,不管我怎麼做。 – 2010-01-13 03:42:15

+0

只要您分配事件「及時」......但不是,它不可能是漂亮的,它是否分配或創建並不重要。就個人而言,我會說寫這個代理是你最好的選擇,但這只是基於對TClientSocket的一個非常快速的瞥見,它將取決於你的確切需求。當然,如果它絕對必須是從組件外部提供的普通TClientSocket,我並不認爲除了當前的解決方案外你可以做什麼。 – 2010-01-13 03:53:57

0

也許你重寫TClientSocket類,並在事件被調用的地方,你也可以調用你自己的例程。唯一的障礙是你需要一個標記爲虛擬或動態的例程來做這個覆蓋,而我沒有檢查過TClientSocket是否這樣做。

在這種情況下,您仍然可以將客戶端套接字公開爲TClientsocket,如果需要的話。