【问题标题】:Selection box of composite component not drawn properly复合组件的选择框未正确绘制
【发布时间】:2026-01-27 03:45:01
【问题描述】:

我有一个复合组件,它由一个TEdit 和一个继承自TCustomControlTButton(是的,我知道TButtonedEdit)组成。编辑和按钮在其构造函数中创建并放置在自身上。

在设计时,选择框未正确绘制 - 我的猜测是编辑和按钮隐藏了它,因为它是为自定义控件绘制的,然后被它们过度绘制。

这里比较:

我在其他 3rd 方组件中也看到了这一点(比如 TcxGrid 也只绘制了选择指示器的外部)

问题:我该如何改变呢?

最简单的复制案例:

unit SearchEdit;

interface

uses
  Classes, Controls, StdCtrls;

type
  TSearchEdit = class(TCustomControl)
  private
    fEdit: TEdit;
  public
    constructor Create(AOwner: TComponent); override;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Custom', [TSearchEdit]);
end;

{ TSearchEdit }

constructor TSearchEdit.Create(AOwner: TComponent);
begin
  inherited;
  fEdit := TEdit.Create(Self);
  fEdit.Parent := Self;
  fEdit.Align := alClient;
end;

end.

【问题讨论】:

  • Delphi 的哪个版本,以防万一
  • 但我认为你不会有任何运气。我认为选择指标是通过 IDE 挂钩控制窗口程序来实现的。并且您的控件在其子项之前绘制。
  • 可能最简单的,在我的脑海中,是在设计时设置自己的绘画。
  • @Gray 你的意思是在父代画,而在子代画?
  • @DavidHeffernan 是的,在设计时在父级中使用 fEdit.PaintTo(...) 之类的东西,然后直接在父级画布上绘制。

标签: delphi controls vcl


【解决方案1】:

正如我在 cmets 中所说,我能想到的最简单的事情是在父级中绘制控件并在设计时将它们“隐藏”给设计师。您可以通过在每个子控件上调用 SetDesignVisible(False) 来完成此操作。然后你用PaintTo在父节点上做画。

使用您的示例,我们得到:

type
  TSearchEdit = class(TCustomControl)
  ...
  protected
    procedure Paint; override;
  ...
  end;

constructor TSearchEdit.Create(AOwner: TComponent);
begin
  inherited;
  fEdit := TEdit.Create(Self);
  fEdit.Parent := Self;
  fEdit.Align := alClient;
  fEdit.SetDesignVisible(False);
end;

procedure TSearchEdit.Paint;
begin
  Inherited;
  if (csDesigning in ComponentState) then
    fEdit.PaintTo(Self.Canvas, FEdit.Left, FEdit.Top);
end;

【讨论】: