Link to home
Start Free TrialLog in
Avatar of skanade
skanade

asked on

How to add Font Property to new component?

I am writing a new component. I want to have  font propery initialized to a default and then changeable from Object Inspector. Can I get an example code on how to initialize? Do I need to free it in destructor as well?

I tried both with no initialization and with initialization but it doesn't work properly. In case of nil, I get can't assign nil from Object Inspector. If I intitialize, I get access violations from IDE.

Please help!
Sanjay
Avatar of kjteng
kjteng

1. declare a tfont field in the private section (fMyFont)
2. declare a corresponding property in published section (Myfont)
3. create fMyFont in the constructor
4. destroy fMyFont before calling inherited destructor

sample:

unit Test;

interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

type
  My = class(TComponent)
  private
    { Private declarations }
    fMyFont: TFont;
  protected
    { Protected declarations }
  public
    { Public declarations }
    constructor create( aOwner: tComponent); override;
    destructor destroy; override;
  published
    { Published declarations }
    property Myfont: TFont read fMyFont write fMyFont;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [ my]);
end;

constructor my.create( aOwner: tComponent);
begin
  inherited create( aOwner);
  fMyFont:= TFont.create;
end;

destructor my.destroy;
begin
  fMyFont.destroy;
  inherited destroy;
end;

end.

Hi

If your component inherits from a TControl (i.e. any "visible" Delphi control) then you can add the following to the published section:  (This works because font is already declared in the Protected section of TControl.)

TMyComponent = class(...)
private
...
public
...
published
  property Font;
end;

If your component does NOT inherit from TControl (e.g. inherits directly from TComponent) then you have to add the font yourself.

E.g.
type
  TMyNewComp = class(TComponent)
  private
    FFont: TFont;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Font: TFont read FFont write SetFont;
  end;

constructor TMyNewComp.Create(AOwner: TComponent);
begin
  inherited;
  FFont := TFont.Create;
end;

destructor TMyNewComp.Destroy;
begin
  FFont.Free;
  inherited;
end;

procedure TMyNewComp.SetFont(Value: TFont);
begin
  FFont.Assign(Value);
end;

Cheers,
JB
(Sorry kjteng, didn't see your answer when I submitted my comment.  -JB)
Not a problem.
As you have mentioned, Skanade might just want to publish an inherited font property only. I have omitted that.
Avatar of skanade

ASKER

Guys,

Thank you for taking time to give full code. However, I have exactly the same code and it doesn't work. I'll try once more and let you know.

Last time I tried it, it failed to retain the font that I changed from Object Inspector. Also, I started getting access violations from IDE. I even tried initializing the font to a particular name and size. No success.

Avatar of skanade

ASKER

Sorry, I tested again. As I said in my last comment, this is the exact code I am using and it doesn't work in Object Inspector. My component is inherited from TComponent. Rest is same as here.

As soon as I press Font in Object Inspector, I get the font dialog only for the first time. Then, if I change the font and press OK, it closes. After that if I press Font again to check whether it changed it, I start getting access violations in VCL30. You can try it yourself.

Thanks,
Sanjay
Avatar of skanade

ASKER

CORRECT ANSWER:
FYI, here is the edited correct answer which I got from the Delphi newsgroup:

I need to go via a SetFont method where I do this:

        SanjayControl.Font := ObjectInspectorFont;

    After doing the assignment, the Object Inspector will
    free its TFont instance. If your property doesn't have a
    write method, this means that your property will point to
    the Object Inspector's instance, which has been freed,
    which results in an Access Violation. This is a frequent
    cause of AVs in new components.

    With a property write method, we perform a "deep-copy"
    of the properties via the Assign method. This copies the
    property values from the ObjectInspectorFont instance to
    our property, which is  exactly what we want.}
  FDefaultFont.Assign(Value);

Hi skanade

You will notice that in my ORIGINAL comment I declared a property like this:
  property Font: TFont read FFont write SetFont;

It uses a procedure "SetFont" which does exactly what you are now doing, i.e. "Assign":
  procedure TMyNewComp.SetFont(Value: TFont);
  begin
    FFont.Assign(Value);
  end;

So, when you said, "However, I have exactly the same code," you must be referring to kjteng's code, not mine???

Regards,
JB
Avatar of skanade

ASKER

JB,

Sorry, I didn't notice the SetFont in your code. The extra comments put in by TeamB member in Delphi newsgroup forced my attention to it.

If you just put a dummy proposed answer, I'll be glad to give you the points as your solution would have worked for Object Inspector which I really was looking for.

Thanks!
Sanjay
ASKER CERTIFIED SOLUTION
Avatar of JimBob091197
JimBob091197

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial