Mega Code Archive

 
Categories / Delphi / Ide Indy
 

Creating a TRect published property that can be changed in the Object Inspector

Title: Creating a TRect published property that can be changed in the Object Inspector Question: The object inspector has an inbuilt ability to edit any TPersistent based object. It uses RTTI to inspect the published properties of the TPersistent descendant and displays them as an expandable property. This is how the constraints property is implemented for example. The following unit provides an implementation of an editable TRect. I use this in controls for specifing margins for example. Answer: unit PersistentRect; interface uses Classes, SysUtils, types; type TPersistentRect = class(TPersistent) private FRect : TRect; FOnChange: TNotifyEvent; function GetRect: TRect; procedure SetRect(const Value: TRect); procedure SetRectBottom(const Value: integer); procedure SetRectLeft(const Value: integer); procedure SetRectRight(const Value: integer); procedure SetRectTop(const Value: integer); protected procedure AssignTo(Dest: TPersistent); override; public property AsRect : TRect read GetRect Write SetRect; constructor create; virtual; published property Left : integer read FRect.Left write SetRectLeft; property Top : integer read FRect.Top write SetRectTop; property Right : integer read FRect.Right write SetRectRight; property Bottom : integer read FRect.Bottom write SetRectBottom; property OnChange : TNotifyEvent read FOnChange write FOnChange; end; implementation { TPersistentRect } procedure TPersistentRect.AssignTo(Dest: TPersistent); begin if Dest is TPersistentRect then with TPersistentRect(Dest) do begin AsRect := Self.AsRect; end else inherited AssignTo(Dest); end; constructor TPersistentRect.create; begin inherited; FOnChange := nil; end; function TPersistentRect.GetRect: TRect; begin result := FRect; end; procedure TPersistentRect.SetRect(const Value: TRect); begin FRect.Left := value.left; FRect.top := value.top; FRect.right := value.right; FRect.bottom := value.bottom; if assigned(FOnChange) then FOnChange(self); end; procedure TPersistentRect.SetRectBottom(const Value: integer); begin FRect.Bottom := Value; if assigned(FOnChange) then FOnChange(self); end; procedure TPersistentRect.SetRectLeft(const Value: integer); begin FRect.Left := Value; if assigned(FOnChange) then FOnChange(self); end; procedure TPersistentRect.SetRectRight(const Value: integer); begin FRect.Right := Value; if assigned(FOnChange) then FOnChange(self); end; procedure TPersistentRect.SetRectTop(const Value: integer); begin FRect.Top := Value; if assigned(FOnChange) then FOnChange(self); end; end. Example To create a panel component with controlable margins........ TPanelWithMargins = class(TCustomPanel) private { Private declarations } FMargins: TPersistentRect; protected { Protected declarations } procedure MarginsChanged(Sender : TObject); procedure AdjustClientRect(var Rect: TRect); override; public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy; override; published { Published declarations } property Margins : TPersistentRect read FMargins write FMargins; end; procedure TPanelWithMargins.AdjustClientRect(var Rect: TRect); begin inherited; Rect.Left := rect.Left + FMargins.Left; Rect.Top := rect.top + FMargins.Top; Rect.Right := rect.Right - FMargins.Right; Rect.Bottom := rect.Bottom - FMargins.Bottom; end; constructor TPanelWithMargins.Create(AOwner: TComponent); begin inherited; FMargins := TPersistentRect.create; FMargins.OnChange := MarginsChanged; FMargins.AsRect := Rect(2,2,2,2); end; destructor TPanelWithMargins.Destroy; begin FreeAndNil(FMargins); inherited; end; procedure TPanelWithMargins.MarginsChanged(Sender: TObject); begin Realign; end;