I am creating a custom control derived from TCustomControl, for example:
type
TMyCustomControl = class(TCustomControl)
private
FText: string;
procedure SetText(const Value: string);
protected
procedure Paint; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Text: string read FText write SetText;
end;
Note, the above is incomplete for purpose of the example to keep it short and simple.
Anyway, in my control I have a Paint event which displays text (from FText field) using Canvas.TextOut.
When my component is added to the Delphi Form Designer (before any user changes can be made to the component) I want the TextOut to display the name of the Component – TButton, TCheckBox, TPanel etc are examples of this with their caption property.
If I try to assign the name of my Component to FText in the constructor it returns empty, eg '';
constructor TMyCustomControl.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FText := Name; //< empty string
ShowMessage(Name); //< empty message box too
end;
If I change FText := Name to FText := 'Name'; it does output the text to my Component so I do know it is not a problem within the actual code, but obviously this outputs ‘Name’ and not the actual Component name like MyCustomControl1, MyCustomControl2 etc.
So my question is, how can you get the name of your Component from its constructor event?
The
Nameproperty has not been assigned yet when the constructor is running. At design-time, the IDE assigns a value to theNameproperty after the component has been dropped onto the Designer, after the control’s constructor has exited. At runtime, theNameproperty is set by the DFM streaming system instead, which is also invoked after the constructor has exited.Either way, the
TControl.SetName()property setter validates the new value, and then sets the new value to the control’sTextproperty to match if the currentTextvalue matches the oldNamevalue and the control’sControlStyleproperty includes thecsSetCaptionflag (which it does by default). When theTextproperty changes for any reason, the control automatically sends itself aCM_TEXTCHANGEDnotification. You can have your control catch that message and callInvalidate()on itself to trigger a new repaint. Inside of yourPaint()handler, simply draw the currentNameas-is, whatever value it happens to be. If it is blank, so be it. Don’t try to force theName, let the VCL handle it for you normally.