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
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
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
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.
As you have mentioned, Skanade might just want to publish an inherited font property only. I have omitted that.
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.
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.
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
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
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) ;
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
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
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
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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('Sample
end;
constructor my.create( aOwner: tComponent);
begin
inherited create( aOwner);
fMyFont:= TFont.create;
end;
destructor my.destroy;
begin
fMyFont.destroy;
inherited destroy;
end;
end.