gpt4 book ai didi

delphi - 如何从继承自另一个自定义控件的自定义控件触发方法?

转载 作者:行者123 更新时间:2023-12-03 18:16:14 25 4
gpt4 key购买 nike

概览

为了更简单地将问题转化为文本,我的控件的继承如下所示:

TCustomListBox > TMyCustomListBox > TMyListBox

TMyCustomListBox的原因是在TCustomListBox的基础上进行扩展,加入一些我自己的新属性和方法,然后我会有其他的TMyListBox 将从 TMyCustomListBox 派生的组件,但也可能有自己的属性和方法。

问题

我面临的问题是无法触发我在 TCustomListBox 中引入的 TMyListBox 中的方法。

考虑到这一点,这里是 TMyCustomListBox 的分解片段,您可以在其中看到我添加的新方法类型 (OnAddition):

type
TOnAdditionEvent = procedure(Sender: TObject; Index: Integer; Value: string) of object;

TMyCustomListBox = class(TCustomListBox)
private
FOnAddition: TOnAdditionEvent;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnAddition: TOnAdditionEvent read FOnAddition write FOnAddition;
property OnClick;
property OnDblClick;
// ...
end;

我这样分配事件:

if Assigned(FOnAddition) then
begin
FOnAddition(Self, SomeIndex, SomeValue);
end;

上面的调用来自:

procedure WndProc(var Message: TMessage); override;

现在我们有了TMyListBox:

type
TMyListBox = class(TMyCustomListBox)
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;

如果我在设计时使用 TMyListBox 的实例并使用新事件,那么在运行时测试时它可以正常工作:

procedure Form1.MyListBox1Addition(Sender: TObject; Index: Integer; Value: string);
begin
ShowMessage('Added Item: [' + Value + '] whose index is: ' + IntToStr(Index));
end;

我如何在 TMyListBox 组件源中做同样的事情,我尝试了一些不同的事情,但要么没有触发事件,要么出现错误。


我尝试过的

1

type
TMyListBox = class(TMyCustomListBox)
protected
procedure Addition(Sender: TObject; Index: Integer; Value: string);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;

constructor TMyListBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
OnAddition := Addition; // shouldn't this call Addition procedure below?
end;

procedure TMyListBox.Addition(Sender: TObject; Index: Integer;
Value: string);
begin
ShowMessage('test'); // doesnt fire
end;

2

同上,只是加入了inherited:

procedure TMyListBox.Addition(Sender: TObject; Index: Integer;
Value: string);
begin
inherited; // no difference
ShowMessage('test'); // doesnt fire
end;

3

我尝试重写 Addition 方法声明:

procedure Addition(Sender: TObject; Index: Integer; Value: string); override;

在基类中找不到 Addition 的错误。

4

我什至尝试将声明更改为:

procedure OnAddition(Sender: TObject; Index: Integer; Value: string);

并从构造函数中删除事件处理程序,仍然没有触发。

我也尝试了一些其他的东西,但此时我遇到了死胡同,所以希望能向正确的方向插入。我真的应该能够解决这个问题,但我认为我在这个问题上停留的时间太长了,我的大脑正在融化,所以我等待最有可能成为一个简单明显的答案:)

谢谢。

最佳答案

constructor TMyListBox.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
OnAddition := Addition; // shouldn't this call Addition procedure below?
end;

这个作业应该工作得很好。不,它不会调用 Addition(),它Addition() 的地址分配给 OnAddition 事件。当事件被触发时,它将调用 Addition()

然而,话虽如此,这是错误的设计。一个组件应该永远分配一个处理器给它自己的事件(尤其是published事件)。正确的解决方案是让 TMyCustomListBox 声明一个触发 OnAdditionvirtual 方法,然后在需要时调用该方法。 TMyListBox(或任何其他后代)然后可以覆盖该方法,如果/当它想要触发用户的 OnAddition< 时调用 inherited/ 事件处理程序。额外的好处是,即使用户没有分配任何事件处理程序,这也允许后代对事件使用react。

试试这个:

type
TOnAdditionEvent = procedure(Sender: TObject; Index: Integer; Value: string) of object;

TMyCustomListBox = class(TCustomListBox)
private
FOnAddition: TOnAdditionEvent;
protected
procedure DoAddition(Index: Integer; Value: string); virtual;
property OnAddition: TOnAdditionEvent read FOnAddition write FOnAddition;
// ...
end;

procedure TMyCustomListBox.DoAddition(Index: Integer; Value: string);
begin
if Assigned(OnAddition) then
OnAddition(Self, Index, Value);
end;

type
TMyListBox = class(TMyCustomListBox)
protected
procedure DoAddition(Index: Integer; Value: string); override;
// ...
published
property OnAddition;
//...
end;

procedure TMyListBox.DoAddition(Index: Integer; Value: string);
begin
ShowMessage('test'); // doesnt fire
inherited;
end;

关于delphi - 如何从继承自另一个自定义控件的自定义控件触发方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26895193/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com