重金请问,如何继承一个property(现在只剩下事件定义了,高分赠送)(200分)

  • 主题发起人 主题发起人 白河愁
  • 开始时间 开始时间

白河愁

Unregistered / Unconfirmed
GUEST, unregistred user!
以 serversocket 为例子, 重写一个控件.
其中需要 Inherited 这个 OnConnect property,
让它执行完它原来的东西后再执行我的程序,然后再执行用户自己写的事件.
 
声明一个同名的Property(实际上你说的是一个事件指针),先执行祖先类的方法,再实现自己的方法
procedure TMyServerSocket.OnConnect(xxxx);
begin
inherited; //这句,执行父类的方法
///下面写你自己的代码
end;
不过你可以看看,TServerSocket类有没有定义动态方法,如果有,直接override这个动态方法即可.
 
关键是
" inherited; //这句,执行父类的方法"

这句的话系统显示为不编译状态,而实际执行中也没执行到这个 inherited,.
头痛好几天的问题了....
 
一般来说应该重载调用事件处的那个函数,比如你说的这个OnConnect,你可以重载TCustomSocket.Event函数(它是从TAbstractSocket而来,并且是虚函数);
还有一种方法是你重新定义一个OnConnect,覆盖掉父类的那个,不过一般不建议用。
 
目前我就是采用覆盖掉父类那个,但这样就无法执行父类中的程序了.....

但是现在我重写的控件也没有代码,不知道应该重载什么东西...
 
根据反编译那个 dcu, 得出
property OnConnect:TNotifySocket read FOnConnect write FOnConnect
而 FOnConnect 则是 私有 中的
FOnConnect: TNotifySocket;

TNotifySocket=procedure(Sender: TObject; Socket: Integer) of object;
 
TServerSocket继承了TCustomSocket的Event方法,而这个方法就是派发各个事件的动态方法,通过override覆盖这个方法,可以给自己的类增加新的行为,下面是TCustomSocket的Event方法源码,供你参考:
procedure TCustomSocket.Event(Socket: TCustomWinSocket; SocketEvent: TSocketEvent);
begin
case SocketEvent of
seLookup: if Assigned(FOnLookup) then FOnLookup(Self, Socket);
seConnecting: if Assigned(FOnConnecting) then FOnConnecting(Self, Socket);
seConnect:
begin
FActive := True;
if Assigned(FOnConnect) then FOnConnect(Self, Socket);
end;
seListen:
begin
FActive := True;
if Assigned(FOnListen) then FOnListen(Self, Socket);
end;
seDisconnect:
begin
FActive := False;
if Assigned(FOnDisconnect) then FOnDisconnect(Self, Socket);
end;
seAccept: if Assigned(FOnAccept) then FOnAccept(Self, Socket);
seRead: if Assigned(FOnRead) then FOnRead(Self, Socket);
seWrite: if Assigned(FOnWrite) then FOnWrite(Self, Socket);
end;
end;
你只要声明一个TMyServerSocket的类,覆盖这个方法即可
type
TMySeverSocket = class (TServerSocket)
protedted
procedure Event(Socket: TCustomWinSocket; SocketEvent: TSocketEvent); override;
end;
实现部分如下写即可:
procedure TMyServerSocket.Event(Socket: TCustomWinSocket; SocketEvent: TSocketEvent);
begin
case SocketEvent of
seConnect:
begin
inherited Event(Socket, SocketEvent);//执行默认的操作
//这里添加你自己增加的代码.
end;
else
inherited Event(Socket, SocketEvent);
end;
end;
 
to zqw0117:
你的意思是要重载处理事件的那个过程吧?
但如果不知道这个过程的名字和原型那怎么办?
 
刚刚发帖子的时候,误删了一部分,请重新看我上上楼的回复,原型都在Delphi里面写了,我的代码也帖了TCustomSocket的Event方法源码.您应该能写一个完整的处理来的.
 
ServerSocket的源码Delphi都已提供了。
 
to zqw0117:
分析那个控件的反编译代码中.....

to dreamisx:
ServerSocket只是举例,我要重载的是另外一个控件.....
 
如果是一个没有源码的控件,唯一的办法就是做一个外壳类,该外壳类和目标类(就是没有源码的那个类)声明全部一致,自己声明和目标类相同的事件,自己内部再声明一个用于目标类事件指针指向的处理函数,该函数的作用就是把目标类出发的事件外发给调用外壳类的外部,如果要加处理,只要在这个外壳类里面添加代码即可.下面举一个简单的例子
type
TInnerClass = class (TObject)
private
FOnConnect: TNotifyEvent;
public
property OnConnect: TNotifyEvent read FOnConnect write FOnConnect;
end;

TWepperClass = class (TObject)
private
FInnerClass : TInnerClass;
FOnConnect: TNotifyEvent;
procedure InnerClassOnConnect(Sender: TObject);
public
constructor Create;
destrucotr Destroy; override;
property OnConnect: TNotifyEvent read FOnConnect write FOnConnect;
end;

constructor TWepperClass.Create;
begin
inherited;
FInnerClass := TInnerClass.Create;
FInnerClass.OnConnect := InnerClassOnConnect;
end;

destructor TWepperClass.Destroy;
begin
FInnerClass.Free;
inherited;
end;

procedure TWepperClass.InnerClassOnConnect(Sender: TObject);
begin
if Assign(FOnConnect) then FOnConnect(Sender);
//附加你的后续处理代码
end;
上述例子可供参考.
 
这样的话是要我在控件内部动态生成一个要继承的控件?然后把事件都接管掉?

这样和
TWepperClass = class (TInnerClass)
相比有什么优缺点?
 
有点就是,TWepperClass几乎就是一个TInnerClass的拷贝(在外部程序看来,行为和属性和TInnerClass毫无区别);但是由于TWepperClass的和TInnerClass的关系已经不是继承的关系了,而是聚合关系,所以,无法在外部程序通过多态来实现TInnerClass的向上或向下转形.
 
正在重写中....

为何 if Assign(FOnEvent) then FOnEvent(Sender);
会说参数不足?

FOnEvent的定义是
FOnEvent: TNotifyEvent;
 
试试这个,不行再说:
type
TMyClass = class(TServerSocket)
private
FMyConnect: TNotifyEvent;
procedure DoMyConnect(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
property OnConnect: TNotifyEvent read FMyConnect write FMyConnect;
end;

implementation

constructor TMyClass.Create(AOwner: TComponent);
begin
inherited;
inherited OnConnect := DoMyConnect;
end;

procedure TMyClass.DoMyConnect(Sender: TObject);
begin
// { TODO : Add Your Code }
if Assigned(FMyConnect) then FMyConnect(Self);
end;
 
请看代码,如何通过?

unit THEUnit;

interface

uses
Windows, SysUtils, Classes,
THEBST;

type
TNotifyEventEx = procedure(Sender: TObject; Level: Integer; Status: AnsiString) of object;

type
TTHE = class(TComponent)
private
//事件
FOnEvent: TNotifyEventEx;
{ FOnReceive: TNotifyReadData;
FOnConnect: TNotifySocket;
FOnDisconnect: TNotifySocket;}


FTHEBST: TTHEBST; //具体控件

//事件实现过程
procedure THEBST_ClassOnEvent(Sender: TObject; Level: Integer; Status: AnsiString);
protected
{ Protected declarations }
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;

published
//事件
property OnEvent:TNotifyEventEx read FOnEvent write FOnEvent;
{ property OnReceive:TNotifyReadData read FOnReceive
write FOnReceive;
property OnConnect:TNotifySocket read FOnConnect
write FOnConnect;
property OnDisconnect:TNotifySocket read FOnDisconnect
write FOnDisconnect;}
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Internet', [TTHE]);
end;

{******************************************************************************}
{* 构建 *}
{******************************************************************************}
constructor TTHE.Create(AOwner: TComponent);
begin
inherited Create(AOwner);

FTHEBST:= TTHEBST.Create(nil);

end;

destructor TTHE.Destroy;
begin
FTHEBST.Free;

inherited;
end;

{******************************************************************************}
{* 事件实现 *}
{******************************************************************************}
procedure TTHE.THEBST_ClassOnEvent(Sender: TObject; Level: Integer; Status: AnsiString);
begin
if Assign(FOnEvent) then
{ if Assign(FOnEvent) then
FOnEvent(Sender, Level, Status);
// if Assign(FOnEvent) then FOnEvent(Sender);}

//附加你的后续处理代码
end;

end.
 
to jeffrey_s:
这样的话应该无法执行原来的事件吧?
 
现在应该只剩下一个问题了。

在要聚合的 THEBST.dcu(没源代码)里有如下的定义

type
TNotifyEvent=procedure(Sender: TObject; Level: Integer; Status: AnsiString) of object;

那在现在的控件中定义一个私有成员
FOnEvent: THEBST.TNotifyEvent;

再定义一个事件
property OnEvent: THEBST.TNotifyEvent read FOnEvent write FOnEvent;

那按道理应该定义一个如下的过程
procedure THEBST_ClassOnEvent(var Level: Integer; const Status: AnsiString);

procedure TXXXX.THEBST_ClassOnEvent(var Level: Integer; const Status: AnsiString);
begin
if Assigned(FOnEvent) then
FOnEvent(Self, Level, Status);

//新增的程序
end;

然后在 Create 的时候如下操作
constructor TXXXX.Create(AOwner: TComponent);
begin
inherited Create(AOwner);

FTHEBST:= TTHEBST.Create(nil);

//事件
FTHEBST.OnEvent:= THEBST_ClassOnEvent;
end;

但现在出现错误
Parameter lists differ
是说参数定义不一致。
尝试把 OnEvent 定义为
procedure TXXXX.THEBST_ClassOnEvent(Sender: TObject; Level: Integer; Status: AnsiString);
也是不成的............

解决了这个问题的话另外还有分付送,谢谢各位~~
 
按理说procedure TXXXX.THEBST_ClassOnEvent(Sender: TObject; Level: Integer; Status: AnsiString);应该是可以的;
如果你已经装了TTHEBST这个控件,那你可以双击它的OnNotifyEvent,看看它生成的事件是什么样的。
 
后退
顶部