1
votes

i am working on a custom component in Delphi -7 for which i have some published properties

   private
     { Private declarations }
     FFolderzip  ,Fimagezip,Ftextzip,FActivatezipComp   : Boolean;
     FMessagebo : string;
   published
    { Published declarations }
    {component Properties}
    {#1.Folder Zip}
    property ZipFolder : Boolean read FFolderzip  write FFolderzip  default False;
    {#2.Send imagezip ?}
    property ZipImage : Boolean read Fimagezip   write Fimagezip   default False;
    {#3.text files}
    property ZipText : Boolean read Ftextzip   write Ftextzip   default False;
    {#4.message}
    property ZipMessage: String read FMessagebo write FMessagebo ; 
    {#5.Activate }
    property ActivateZipper: Boolean read FActivatezipComp write  FActivatezipComp Default false;
   end;

When the user drops the component on the application, ActivateZipper properties give the use a option to activate/enable or deactivate/disable the component from executing. The component creates a file so in the constructor i have this, CreateATextFileProc will create the file in the application folder.So if i check in the constructor if the ActivateZipper is true or false..

i have a constructor

     constructor TcomProj.Create(aOwner: TComponent);
     begin
       inherited;
       if ActivateZipper then CreateATextFileProc;
     end;

The ActivateZipper is always false even if i set it to true in the object inspector. How can the component be disabled from doing it working with published property?

2
ActivateZipper is always False in the constructor because objects are zero initialised. It will be set True when the properties are streamed in. Are you aware that most apps run without sufficient rights to write to the application folder?David Heffernan
@DavidHeffernan ok, and for sufficient rights i guess the manifest file for higher privileges can be used ..since the component is internal now we can take care hopefully of thatPresleyDias
@PresleyDias, I've seen few of your questions related to this same component and I think you don't quite understand Delphi component philosophy. Therefore, I wholeheartedly recommend that you read Delphi Component Design by Danny Thorpe. Although this book is very old, most of its contents still apply to this subject.LightBulb
@LightBulb yes, im a new to this component creation,modification and customization. ..thank you for the link..wholeheartedly appreciatedPresleyDias
@DavidHeffernan C:\Documents and Settings\Myname\Application Data\myfolder (i guess this is better) thank you:)PresleyDias

2 Answers

4
votes

The constructor is too early. The design-time property values have not been streamed into the component yet. You need to wait until your component's Loaded() method is called before you can then act on the values. If you create the component dynamically at run-time, you also need a property setter since there are no DFM values and thus Loaded() will not be called.

type
  TcomProj = class(TComponent)
  private 
    ...
    procedure SetActivateZipper(Value: Boolean);
  protected
    procedure Loaded; override;
  published 
    property ActivateZipper: Boolean read FActivatezipComp write SetActivateZipper; 
  end; 

procedure TcomProj.SetActivateZipper(Value: Boolean);
begin
  if FActivatezipComp <> Value then
  begin
    FActivatezipComp := Value;
    if ActivateZipper and ((ComponentState * [csDesigning, csLoading, csLoading]) = []) then
      CreateATextFileProc; 
  end;
end;

procedure TcomProj.Loaded;
begin
  inherited;
  if ActivateZipper then CreateATextFileProc; 
end;
2
votes

ActivateZipper is always False even if I set it to True in the object inspector.

Your activation code is now placed in the constructor. A few things about that:

  • In the constructor, all private fields are zero (0, '', null, nil, depending on type) initialized. If you do not set it otherwise, then these fields remain zero once the component is created.
  • When you are changing properties with the object inspector, the component is already created.
  • Your code will never run.
  • When you do want to initialize it otherwise at creation, then change also the default storage specifier.

What you need is a property setter that will be invoked whenever the property is changed by means of object inspector or code:

  private
    procedure SetZipperActive(Value: Boolean);
  published
    property ZipperActive: Boolean read FZipperActive write SetZipperActive default False;

procedure TcomProj.SetZipperActive(Value: Boolean);
begin
  if FZipperActive <> Value then
  begin
    FZipperActive := Value;
    if FZipperActive then
      CreateATextFile
    else
      ...
end;

You might consider to turn off this functionality at design-time, since it is likely that you want the actual zipping only at run-time. Then test for the csDesigning flag in ComponentState:

procedure TcomProj.SetZipperActive(Value: Boolean);
begin
  if FZipperActive <> Value then
  begin
    FZipperActive := Value;
    if csDesigning in ComponentState then
      if FZipperActive then
        CreateATextFile
      else
        ...
end;