Reputation: 1760
Using the Delphi XE2 wizard to create a component, I have choose the TPanel to inherit from, and change defaults of some properties to fit my application.
My problem is to change the default of Margins:
TControl = class(TComponent)
...
property Margins: TMargins read FMargins write SetMargins;
Margins is a TMargin class declared with 4 properties that I need to redefine the defaults:
TMargins = class(TPersistent)
published
property Left: TMarginSize index 0 read FLeft write SetMargin default 3;
property Top: TMarginSize index 1 read FTop write SetMargin default 3;
property Right: TMarginSize index 2 read FRight write SetMargin default 3;
property Bottom: TMarginSize index 3 read FBottom write SetMargin default 3;
I can/will be setting on code the margins when the constructor of the component is called, however I have no idea how to redefine these defaults above in order to show up on the property editor.
Upvotes: 8
Views: 3268
Reputation: 54812
You can declare your TMargins
descendant with your own defaults to use in your panel
type
TMyMargins = class(TMargins)
protected
class procedure InitDefaults(Margins: TMargins); override;
published
property Left default 10;
property Top default 10;
property Right default 10;
property Bottom default 10;
end;
class procedure TMyMargins.InitDefaults(Margins: TMargins);
begin
with Margins do begin
Left := 10;
Right := 10;
Top := 10;
Bottom := 10;
end;
end;
then when you create your panel, dismiss the existing one and use yours
TMyPanel = class(TPanel)
private
procedure DoMarginChange(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
end;
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Margins.Free;
Margins := TMyMargins.Create(Self);
Margins.OnChange := DoMarginChange;
end;
procedure TMyPanel.DoMarginChange(Sender: TObject);
begin
// same as in TControl which is private
RequestAlign;
end;
The margins will be stored in the dfm only when they differ from the default.
Although I don't know why the above works... The problem with the above code is, Margins
property have a setter which only assigns to the margins (left, right..). The code never writes to the backing field, but it still works. The line
Margins := TMyMargins.Create(Self);
is effectively same as
TMyMargins.Create(Self);
which also works.
By 'works' I mean, it works. The margins, f.i., gets properly destroyed, not because of ownership etc.. (margins iş a TPersistent
, not a component) but right when the ascendant TControl
calls FMargins.Free
.
Anyway, since I don't understand how it works, as a safer although hacky approach, I'd use this:
constructor TMyPanel.Create(AOwner: TComponent);
var
Addr: NativeUInt;
begin
inherited Create(AOwner);
Addr := NativeUInt(@Margins);
Margins.Free;
PUINT_PTR(Addr)^ := NativeUInt(TMyMargins.Create(Self));
Margins.OnChange := DoMarginChange;
end;
Upvotes: 8