Home > Software engineering >  Using and publishing events at the same time in a Delphi component
Using and publishing events at the same time in a Delphi component

Time:10-29

I have a class that is a descendant of TImage32. I need to use the event like onm ouseMove, so the code assigns my onm ouseMove event in Create(). But if the user installs this component in Delphi and assigns another onm ouseMove event, my event is replaced.

My current solution is to inherit from TCustomImage32 and do not publish the onm ouseMove property (all other properties yes), but create a new onm ouseMove2 property that can be assigned by the user, and the code calls onm ouseMove2 in my assigned onm ouseMove event if onm ouseMove2 is assigned.

Is there a better solution to this problem? To keep the event name for example onm ouseMove and have my own event assigned too?

type
    TAudioBezierCurvesInteractive = class (TCustomImage32)
    private
        FOnMouseMove2: TImgMouseMoveEvent;
        procedure ImgMouseMoveEvent(Sender: TObject; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
    public
        Constructor Create(AOwner: TComponent); override;
    published
        property onm ouseMove2: TImgMouseMoveEvent read FOnMouseMove2 write FOnMouseMove2;
        //* Original published properties
        property Align;
        property Anchors;
        property AutoSize;
        etc. ...

constructor TAudioBezierCurvesInteractive.Create(AOwner: TComponent);
begin
    inherited;
    onm ouseMove := ImgMouseMoveEvent;
end;

procedure TAudioBezierCurvesInteractive.ImgMouseMoveEvent(Sender: TObject; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
begin
    ...my code here...
    if Assigned(FOnMouseMove2) then begin
        FOnMouseMove2(Sender, Shift, X, Y, Layer);
    end;
end;

CodePudding user response:

A component should never assign handlers to its own events. That causes issues for users, as you have discovered.

The correct solution is to override the virtual methods that fire the events, eg:

type
  TAudioBezierCurvesInteractive = class (TImage32)
  protected
    procedure MouseMove(Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); override;
  end;

procedure TAudioBezierCurvesInteractive.MouseMove(Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer;
begin
  ...my code here...
  inherited;
end; 

CodePudding user response:

Better override MouseMove, do your code and call inherited. No need for wiring the event or introducing a second one.

type
    TAudioBezierCurvesInteractive = class (TCustomImage32)
    protected
        procedure MouseMove(Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); override;
    published
        //* Original published properties


procedure TAudioBezierCurvesInteractive.MouseMove(Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer);
begin
    { ...my code here... }
    inherited;
end;
  • Related