Display a warning when dropping a component on a form at design time

Solution 1:

There is protected dynamic method TComponent.PaletteCreated, which is called only in one case: when we add this component to a form from component palette.

Responds when the component is created from the component palette.

PaletteCreated is called automatically at design time when the component has just been created from the component palette. Component writers can override this method to perform adjustments that are required only when the component is created from the component palette.

As implemented in TComponent, PaletteCreated does nothing.

You can override this method to show warning, so it will alert the user just one time, when he tries to put it to form.

UPDATE

I couldn't make this procedure work in Delphi 7, XE2 and Delphi 10 Seattle (trial version), so it seems that call to PaletteCreated from IDE is not implemented.

I sent report to QC:http://qc.embarcadero.com/wc/qcmain.aspx?d=135152 maybe developers will make it work some day.

UPDATE 2

There are some funny workarounds, I've tried them all this time, works normally. Suppose that TOldBadButton is one of components that shouldn't be used. We override 'Loaded' procedure and WMPaint message handler:

TOldBadButton=class(TButton)
private
  fNoNeedToShowWarning: Boolean; //false when created
  //some other stuff
protected
  procedure Loaded; override;
  procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  //some other stuff
end;

and implementation:

procedure TBadOldButton.Loaded;
begin
  inherited;
  fNoNeedToShowWarning:=true;
end;

procedure TOldBadButton.WMPaint(var Message: TWMPAINT);
begin
  inherited;
  if (csDesigning in ComponentState) and not fNoNeedToShowWarning then begin
    Application.MessageBox('Please, don''t use this component','OldBadButton');
    fNoNeedToShowWarning:=true;
  end;
end;    

The problem is, this works only for visual components. If you have custom dialogs, imagelists etc, they never get WMPaint message. In that case we can add another property, so when it is shown in object inspector, it calls getter and here we display warning. Something like this:

  TStupidOpenDialog = class(TOpenDialog)
  private
    fNoNeedToShowWarning: boolean;
    function GetAawPlease: string;
    procedure SetAawPlease(value: string);
    //some other stuff
  protected
    procedure Loaded; override;
    //some other stuff
  published
    //with name like this, probably will be on top in property list
    property Aaw_please: string read GetAawPlease write SetAawPlease;
  end;

implementation:

procedure TStupidOpenDialog.Loaded;
begin
  inherited;
  fNoNeedToShowWarning:=true; //won't show warning when loading form
end;

procedure TStupidOpenDialog.SetAawPlease(value: string);
begin
//nothing, we need this empty setter, otherwise property won't appear on object
//inspector
end;

function TStupidOpenDialog.GetAawPlease: string;
begin
  Result:='Don''t use this component!';
  if (csDesigning in ComponentState) and not fNoNeedToShowWarning then begin
    Application.MessageBox('Please, don''t use this component','StupidOpenDialog');
    fNoNeedToShowWarning:=true;
  end;
end;

Older versions of Delphi always scroll object inspector to the top when new component is added from palette, so our Aaw_please property will surely work. Newer versions tend to start with some chosen place in property list, but non-visual components usually have quite a few properties, so it shouldn't be a problem.