如何处理复合组件中子元素的双击事件?

6
我基于 TCustomPanel 创建了一个新的复合组件。 它包括两个标签和一个图片,覆盖整个面板,布局如下(下部分不太重要):

控件布局

我的问题是如何导出任何一个控件的双击功能?在新控件的双击事件中,能否管理其子控件的双击事件?

不是很清楚您是否希望所有控件同时响应双击事件,还是每个控件都有自己的双击事件处理程序。 - Gabriel
2个回答

4

我认为你应该使用以下方法来完成:

  1. 向复合组件添加一个OnDblClick事件。
  2. 向你的复合组件添加一个名为FOnInternalDblClick(名称不重要)的方法,与TNotifyEvent兼容。
  3. FOnInternalDblClick内部,执行复合组件的OnDblClick
  4. 在复合组件的构造函数中,将FOnInternalDblClick分配给你希望管理事件的每个组件的OnDblClick事件。

示例代码:

TMyCompoundComponent = class(TCustomPanel)
protected
  FOnDblClick : TNotifyEvent;
  procedure FOnInternalDblClick(ASender : TObject);
public
  constructor Create(AOwner : TComponent); override;
published
  property OnDblClick : TNotifyEvent read FOnDblClick write FOnDblClick;
end;

constructor TMyCompoundComponent.Create(AOwner : TComponent);
begin
  inherited;
  //Lab1.OnDblClick := FOnInternalDblClick;
  //Lab2.OnDblClick := FOnInternalDblClick;
  //...
end;

procedure TMyCompoundComponent.FOnInternalDblClick(ASender : TObject);
begin
  if(Assigned(FOnDblClick))
  then FOnDblClick(ASender);
end;

注意:

在复合组件的OnDblClick事件处理程序中,ASender参数将是内部组件(Lab1Lab2Lab3 ...)。如果您希望将复合组件本身作为ASender参数接收,可以通过传递Self而不是ASender来更改FOnInternalDblClick方法:

procedure TMyCompoundComponent.FOnInternalDblClick(ASender : TObject);
begin
  if(Assigned(FOnDblClick))
  then FOnDblClick(Self);
end;

非常感谢,正是我所需要的。 最好的祝福。 - Laurent Saragosti
你应该坚持使用经典的“if assigned()…”。 - Gabriel

3

您的两个请求都是可行的。这取决于您想要做什么。如果您想要为每个子项单独编写程序代码,则需要创建三个额外的公开属性,并将它们映射到相应的子组件属性。像这样(仅展示一个子组件 - 重复另外2个):

type
  TMyPanelForm1 = class( TPanel )
  private
    fLabel1, fLabel2 : TLabel;
    fImage : TImage;
    procedure SetLabel1DblClick(const Value: TNotifyEvent);
    function GetLabel1DblClick: TNotifyEvent;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property OnLabel1DblClick : TNotifyEvent
             read GetLabel1DblClick write SetLabel1DblClick;
  end;
...
function TMyPanelForm1.GetLabel1DblClick: TNotifyEvent;
begin
  Result := fLabel1.OnDblClick;
end;

procedure TMyPanelForm1.SetLabel1DblClick(const Value: TNotifyEvent);
begin
  fLabel1.OnDblClick := Value;

end;

另一方面,如果你希望控件表现为一个统一的控件,其中所有三个子控件“继承”主组件的双击事件,你只需这样进行级联分配:

  TMyPanelForm2 = class( TPanel )
  private
    fLabel1, fLabel2 : TLabel;
    fImage : TImage;
    function GetOnDblClick: TNotifyEvent;
    procedure SetOnDblClick(const Value: TNotifyEvent);
  public
    constructor Create(AOwner: TComponent); override;
  published
    property OnDblClick : TNotifyEvent
             read GetOnDblClick write SetOnDblClick;
  end;
...
function TMyPanelForm2.GetOnDblClick: TNotifyEvent;
begin
  Result := inherited OnDblClick;
end;

procedure TMyPanelForm2.SetOnDblClick(const Value: TNotifyEvent);
begin
  inherited OnDblClick := Value;
  fLabel1.OnDblClick := Value;
  fLabel2.OnDblClick := Value;
  fImage.OnDblClick := Value;
end;

其他解决方案也是可以的。

谢谢Dsm,这实际上是第二种解决方案。我也尝试过这种方法,但是我漏掉了一部分。 - Laurent Saragosti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接