【问题标题】:Display a warning when dropping a component on a form at design time在设计时将组件放在表单上时显示警告
【发布时间】:2016-02-28 19:44:00
【问题描述】:

我正在整理一个大型遗留项目中使用的组件,我已经消除了 220 个自定义组件中的大约 90 个,将它们替换为标准的 Delphi 控件。剩下的一些组件需要大量的工作才能删除,而我没有。我想阻止任何人额外使用其中一些组件,并且想知道如果在设计时将组件放在表单上,​​是否有一种显示消息的方法 - 例如“不要使用此控件,使用x 或 y 代替”。

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

【问题讨论】:

  • 你没有任何介绍或培训就让人们去写代码?
  • 一种可能的方法是,当控件安装到工具面板中时,让注册单元将过时的控件移动到它自己的工具面板类别中,并将其命名为“我的控件(过时)”任何查看工具调色板的人都会注意到标题已过时的方式。
  • 更好的是,在每个此类组件的构造函数中,只需添加MessageDlg('Do not use this!', mtError, [mbOK], 0);(当然首先要检查您是否处于设计阶段)。
  • 没错,实际上 Craig 的建议似乎是您的最佳行动路线。
  • AFAIK,注册组件而不将其添加到工具面板的记录方法是 RegisterNoIcon

标签: delphi components


【解决方案1】:

有一个受保护的动态方法TComponent.PaletteCreated,它只在一种情况下被调用:当我们从组件面板添加这个组件到一个表单时。

从组件面板创建组件时响应。

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

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

您可以覆盖此方法以显示警告,因此当用户尝试将其放入表单时,它只会提醒用户一次。

更新

我无法让这个程序在 Delphi 7、XE2 和 Delphi 10 Seattle(试用版)中运行,因此似乎没有实现从 IDE 调用 PaletteCreated。

我已将报告发送给 QC:http://qc.embarcadero.com/wc/qcmain.aspx?d=135152 也许开发者有一天会让它工作。

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

问题是,这仅适用于视觉组件。如果您有自定义对话框、图像列表等,它们永远不会收到 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 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 总是将对象检查器滚动到顶部,因此我们的 Aaw_please 属性肯定会起作用。较新的版本往往从属性列表中的某个选定位置开始,但非可视组件通常具有相当多的属性,因此应该不是问题。

【讨论】:

  • 有趣,在我使用和编写 VCL 组件的这些年里,我从未见过或听说过PaletteCreated()
  • 第一次听说这个。太棒了
  • @Alister 我想知道您为什么没有接受这个答案(或者最近确实没有接受任何其他答案)。由于这显然是您问题的完美答案,我只能假设您已经忘记了接受答案的礼仪。
  • @DavidHeffernan 虽然该解决方案看起来相当简单,但我实际上并不能让它发挥作用。将组件构造函数放在表单上时会调用它,但 PaletteCreated 似乎没有。我的测试代码看起来不错,包被重新安装到 IDE 中就好了,但是 PaletteCreated 没有触发。也许我做错了什么,因为如果这个答案不起作用,我很惊讶这么多人会投票赞成这个答案。
  • @DavidHeffeman,Alister,对不起,我也无法正常工作。似乎在任何 Delphi 版本中都没有实现调用 PalleteCreated form IDE。没想到,delphi 文档从来没有让我失望过。我认为,这可能算作一个错误并发送了 QC 报告,还可以在更新中看到一些解决方法,它们可以工作(检查了几个版本),但不幸的是它们并不那么优雅。
【解决方案2】:

要确定组件的首次创建时间(放置在表单上)?

覆盖 "CreateWindowHandle" 并在其中使用以下 if 语句:

if (csDesigning in ComponentState) and not (csLoading in ComponentState) then
  // We have first create

这里有更多详细信息>> Link

【讨论】:

    猜你喜欢
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多