我有自定义组件(缩减)
TMyComponent = class(TComponent)
public
procedure ClientConnected;
published
property ClientSocket: TClientSocket Read ...etc
现在我已进入ClientSocket Call ClientConnected的OnConnect事件,例如
procedure TForm1.ElvinClient1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
MyComponent1.ClientConnected;
end;
有没有办法在TMyComponent类中执行此操作而不需要外部事件?
编辑:
忘了说ClientSocket不是由组件创建的,它是在运行时分配的。
我也尝试过私人过程
procedure TMyComponent.OnClientConnected(sender: TObject);
begin
ClientConnected;
if Assigned(oldOnClientConnected) then
oldOnClientConnected(sender);
end;
和ClientSocket的setter
procedure TMyComponent.SetClientSocket(const Value: TClientSocket);
begin
fClientSocket := Value;
oldOnClientConnected:= fClientSocket.OnElvinConnected;
fClientSocket.oldOnClientConnected:= OnClientConnected;
end;
但我觉得它会回来困扰我......
答案 0 :(得分: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;
当然,它没有编译(我确定,从未尝试过),但这只是一个简短的想法。也许我想念一些事情,如果你有错误可以让我知道。
答案 1 :(得分:0)
是的,您可以在组件中实现具有该签名的过程,并在构造TClientSocket时将其分配给事件。
HOWEVER ...因为您公开了ClientSocket,这意味着可以使用您的组件覆盖代码中的事件分配。根据事情发生的顺序以及将要使用组件的人员,这对您来说可能不是问题 - 但您可能需要考虑将ClientSocket设为私有或受保护,或者可能要编写一个简单的代理,然后将其用于确保在用户的事件处理程序之前调用ClientConnected。
答案 2 :(得分:0)
也许你可以覆盖TClientSocket类,并且在调用事件的地方你也可以调用自己的例程。唯一的障碍是你需要一个标记为虚拟或动态的例程来执行此覆盖,并且我没有检查TClientSocket是否这样做。
在这种情况下,您仍然可以将客户端套接字公开为TClientsocket,如果需要的话。