Search code examples
delphicontrolsvcl

Selection box of composite component not drawn properly


I have a composite component that consists of a TEdit and a TButton (yes, I know about TButtonedEdit) that inherits from TCustomControl. The edit and button are created in its constructor and placed on itself.

At designtime the selection box is not drawn properly - my guess is that the edit and button are hiding it because its been drawn for the custom control and then overdrawn by them.

Here the comparison:

enter image description here

I have also seen this for other 3rd party components (like the TcxGrid also only draws the outer part of the selection indicator)

Question: how can I change that?

Most simple case for reproducing:

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.

Solution

  • As I said in the comments, the easiest thing I can think of is to paint the controls in the parent and "hide" them from the designer at design time. You can do this by calling SetDesignVisible(False) on each of the child controls. Then you use PaintTo to do the painting on the parent.

    Using your example we get:

    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;