Bo Real
Bo Real

Reputation: 136

Redeclare Width property for a custom Delphi component

I have a custom Delphi component descending from TGraphicControl. Its class is declared as follows :

TMyLabel = class(TGraphicControl)
private
  ...
protected
  ...
public
  ...
published
  property Height;
  property Width write SetWidth;
  ...
end;

The implementation of SetWidth lies further :

procedure TMyLabel.SetWidth(const Value: Integer);
begin
  if (Value >= 0) and (Value <> Width)
  then begin
    inherited Width := Value;
    // Do some other stuff
    ...
  end;
  MessageDlg('Test', mtInformation, [mbOK], 0);
end;

I currently get SetWidth called when the width of the component is changed programmatically at runtime or at design time by entering a value in the corresponding field of the object inspector. However, when I resize the component at design time using the mouse, the object inspector 'Width' field is updated but no message box shows up, so my SetWidth procedure is not called.

I need SetWidth to be called while mouse-resizing the component, so that I can set a flag for the Paint procedure to know when it must do some other stuff (besides just redrawing the component). Is there a way to achieve this ?

Upvotes: 4

Views: 2791

Answers (3)

Lars Truijens
Lars Truijens

Reputation: 43635

While Mason Wheeler's answer is the answer to your question, I would like to warn you.

Overriding properties can give strange results since you can't have 'virtual' properties and SetWidth is also not virtual. If someone is using a descendant of your class to set the Width property, your code would not be called. Therefore I advice against overriding properties in this way.

var Control: TControl;
begin
 Control := MyLabel;
 Control.Width := 5000; // TMyLabel.SetWidth is not called!!

Furthermore: setting the Width property is not the only way to change the width of a control as Deltics explains. You should override TControl.SetBounds.

var MyLabel: TMyLabel;
begin
 MyLabel.SetBounds(0, 0, 100, 100); // TMyLabel.SetWidth nor TControl.SetWidth is called!!

But it seems like you want to limit the width of your control. Then you better override TControl.CanResize which is made for that purpose. Or if you just want to react to a resize of any kind you better override TControl.Resize.

Upvotes: 7

Deltics
Deltics

Reputation: 23056

I can't check right now, but iirc I suspect that the designer resizes your control using SetBounds() rather than setting individual left, top, width and height properties.

Fortunately, SetBounds() is virtual so you can simply override this in your custom control class.

Upvotes: 6

Mason Wheeler
Mason Wheeler

Reputation: 84650

When you redeclare Width, you need to specify both the read and the write for it or you won't be able to modify it in the Object Inspector. If you're not going to change the way reading works, then just give it a dummy function:

procedure TMyLabel.GetWidth: Integer;
begin
  result := inherited Width;
end;

Upvotes: 4

Related Questions