Why I got another size of a component in IDE?

597 Views Asked by At

Using Delphi 6 Prof.

I created a bevel component for separation.

Because I used spacers with 8 pixel (width x height) I thought that I create this component, and when I put it on a Form, I need only to set Align - and that's all.

type
  TSSpacer = class(TBevel)
  public
    constructor Create(aOwner: TComponent); override;
  published
    //property Width default 8;
    //property Height default 8;
    property Shape default bsSpacer;
end;

constructor TSSpacer.Create(aOwner : TComponent);
begin
  inherited Create(aOwner);
  Shape := bsSpacer;
  Width := 8;
  Height := 8;
end;

But when I use this code (with or without "defaults") the result is 140 x 41 pixels in the IDE.

So why does it not size to 8 x 8? And what is also interesting: the default TBevel is 50 x 50.

What causes this resizing?

2

There are 2 best solutions below

2
On BEST ANSWER

TLama hits the nail in his comments: somehow the designer prevents components from becoming too small. Strange though that the designer does not set this minimum size (10 x 10), but instead seems to randomly set the size to arbitrary values: 140 x 41 in D6 as stated by OP, and 100 x 41 here in D7.

Well, since TBevel does use nor publish the AutoSize property, and that property name kind of relates to wished behaviour, I chose to stretch its use:

type
  TSSPacer = class(TBevel)
  protected
    procedure SetParent(AParent: TWinControl); override;
  public
    constructor Create(AOwner: TComponent); override;
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
  published
    property Shape default bsSpacer;
  end;

constructor TSSPacer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Shape := bsSpacer;
end;

procedure TSSPacer.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  if AutoSize then
    inherited SetBounds(ALeft, ATop, 8, 8)
  else
    inherited SetBounds(ALeft, ATop, AWidth, AHeight);
end;

procedure TSSPacer.SetParent(AParent: TWinControl);
begin
  AutoSize := (csDesigning in ComponentState) and (Parent = nil) and
    (AParent <> nil);
  inherited SetParent(AParent);
end;

This works here in D7, but a more reliable implementation might be:

  private
    FFixDesignSize: Boolean;

procedure TSSPacer.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
begin
  if FFixDesignSize then
  begin
    inherited SetBounds(ALeft, ATop, 8, 8);
    FFixDesignSize := False;
  end
  else
    inherited SetBounds(ALeft, ATop, AWidth, AHeight);
end;

procedure TSSPacer.SetParent(AParent: TWinControl);
begin
  FFixDesignSize := (csDesigning in ComponentState) and (Parent = nil) and
    (AParent <> nil);
  inherited SetParent(AParent);
end;

And to complete this answer with a call stack of dropping this control in the designer on a form:

- Before SetBounds
- After SetBounds
- Before SetBounds
- After SetBounds
- Before SetParent
    - Before SetBounds
    - After SetBounds
- After SetParent
- Before SetBounds
- After SetBounds
- Before SetParent
- After SetParent

But I think you should not rely on this specific order or number of calls: I suspect it might differ between Delphi versions.

3
On

Found an article that should explain it.. I think you need to override TControl's SetBounds.

Read more here http://www.delphidabbler.com/tips/77