Delphi 在设计时将组件拖放到窗体上时显示警告

Delphi 在设计时将组件拖放到窗体上时显示警告,delphi,components,Delphi,Components,我正在整理一个大型遗留项目中使用的组件,我删除了220个自定义组件中的90个,用标准的Delphi控件替换它们。其余的一些组件需要大量的工作才能删除,而我没有可用的。我想防止任何人额外使用其中一些组件,我想知道如果在设计时将组件放到表单上,是否有一种方式来显示消息,比如“不要使用此控件,而是使用x或y” 另一种可能是隐藏组件托盘上的控件(但在设计时仍在表单上正确呈现控件)。有一种受保护的动态方法,仅在一种情况下调用:当我们从组件调色板将此组件添加到表单时 从组件选项板创建组件时响应 当刚从组件选

我正在整理一个大型遗留项目中使用的组件,我删除了220个自定义组件中的90个,用标准的Delphi控件替换它们。其余的一些组件需要大量的工作才能删除,而我没有可用的。我想防止任何人额外使用其中一些组件,我想知道如果在设计时将组件放到表单上,是否有一种方式来显示消息,比如“不要使用此控件,而是使用x或y”


另一种可能是隐藏组件托盘上的控件(但在设计时仍在表单上正确呈现控件)。

有一种受保护的动态方法,仅在一种情况下调用:当我们从组件调色板将此组件添加到表单时

从组件选项板创建组件时响应

当刚从组件选项板创建组件时,将在设计时自动调用PaletteCreated。组件编写器可以重写此方法,以执行仅在从组件选项板创建组件时才需要的调整

正如在TComponent中实现的那样,PaletteCreated什么都不做

您可以重写此方法以显示警告,因此当用户尝试将其设置为表单时,它只会提醒用户一次

更新

我无法在Delphi7、XE2和Delphi10(试用版)中运行此过程,因此似乎没有实现从IDE创建的对Palette的调用

我向QC发送了报告: 也许有一天开发者会让它工作

更新2

有一些有趣的解决办法,我一直在尝试,效果正常。假设TOldBadButton是不应该使用的组件之一。我们重写“已加载”过程和WMPaint消息处理程序:

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;
和执行:

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;    
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;
问题是,这只适用于可视组件。如果您有自定义对话框、图像列表等,它们永远不会收到WMPaint消息。在这种情况下,我们可以添加另一个属性,所以当它显示在对象检查器中时,它调用getter,在这里我们显示警告。大概是这样的:

  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;
实施:

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;    
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;

当从调色板添加新组件时,旧版本的Delphi总是将object inspector滚动到顶部,所以我们的Aaw_please属性肯定会工作。较新的版本往往从属性列表中的某个选定位置开始,但非可视组件通常有相当多的属性,因此这不应该是一个问题。

您只是让人们在没有任何介绍或培训的情况下阅读代码?一种可能的方法是将控件安装到工具选项板中,让注册部门将过时的控件移动到其自己的工具选项板类别中,并将其命名为“我的控件(过时)”,这样任何查看工具选项板的人都会注意到标题为“过时”。更妙的是,在每个组件的构造函数中,只需添加
MessageDlg('请勿使用此!',mtError,[mbOK],0);
(当然,首先检查您是否在设计时).没错,实际上Craig的建议似乎是你最好的行动方式。好吧,有文档记载的注册组件而不将其添加到工具选项板的方法是
RegisterNoIcon
。有趣的是,在我使用和编写VCL组件的这么多年中,我从未见过或听说过
PaletteCreated()
。第一次听到这个消息。Awesome@Alister我想知道你为什么不接受这个答案(或者最近的任何其他答案)。由于这显然是对你问题的完美回答,我只能假设你已经忘记了接受答案的礼仪。@DavidHeffernan虽然解决方案看起来相当简单,但我实际上无法让它工作。组件构造函数在窗体上删除时被调用,但Palette没有创建似乎不是。我的测试代码看起来不错,软件包重新安装到IDE中很好,但PaletteCreated没有启动。也许我做错了什么,因为我很惊讶,如果这个答案不起作用,那么很多人会投票支持它。@Davidheffman,Alister,对不起,伙计们,我也不能让它起作用。似乎调用PalleteCreated是从IDE中创建的没有在任何Delphi版本中实现。没想到,Delphi文档以前从未让我失望过。我认为,这可能算作一个bug,并发送了QC报告,还可以在更新一些解决方法中看到,它们可以工作(在多个版本中检查),但不幸的是,它们不是那么优雅。