如何处理复合组件中子项的双击?

How to handle double click from childs in compound component?

我基于 TCustomPanel 创建了一个新的复合组件。 在上面我有两个标签和一张图片,覆盖了所有的表面,看这个布局(下部不太重要):

我的问题是如何导出这些控件的双击功能?是否可以使用新控件的双击(事件)来管理其上的子控件?

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

  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;

你的两个要求都可以。这取决于你想做什么。如果您希望能够在程序中为每个子项单独编写代码,您需要为组件创建三个额外的已发布属性并将它们映射到相应的子组件属性。像这样(仅针对一个子组件显示 - 对其他 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;

另一方面,如果您希望控件像一个统一控件一样运行,其中所有三个子控件 'inherit' 主要组件双击,您只需像这样向下分配:

  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;

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