Recent

Author Topic: [SOLVED] TIniPropStorage: how to add an array to my INI-file?  (Read 5046 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
[SOLVED] TIniPropStorage: how to add an array to my INI-file?
« on: January 26, 2017, 03:55:45 pm »
My program uses a TIniPropStorage to save some data in an INI-file. This works fine for objects which are created by the object inspector and for "normal" variables like integers, but not for an array of TColorBoxes.
My code looks like:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
  9.  IniPropStorage, ColorBox;
  10.  
  11. type
  12.  ColorBoxArray = array of TColorBox;
  13.  { TForm1 }
  14.  
  15.  TForm1 = class(TForm)
  16.   ColorBox1: TColorBox;
  17.   IniPropStorage1: TIniPropStorage;
  18.   procedure FormCreate(Sender: TObject);
  19.  private
  20.    CB: ColorBoxArray;
  21.    FField1: Integer;
  22.  public
  23.  published
  24.    property CBA: ColorBoxArray read CB write CB;
  25.    property Field1: Integer read FField1 write FField1;
  26.  end;
  27.  
  28. var
  29.  Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.FormCreate(Sender: TObject);
  38.    var i: integer;
  39.    begin
  40.    Field1:=55;
  41.    SetLength(CB,3); // is 20 in my real program
  42.    for i:=0 to High(CBA) do
  43.       begin
  44.       CBA[i]:=TColorBox.Create(self);
  45.       CBA[i].Top:=10;
  46.       CBA[i].Left:=i*120;
  47.       CBA[i].Parent:=self;
  48.       end;
  49.    Form1.SessionProperties:='Top;Left;ColorBox1.Selected;'
  50.      + 'CBA[1].Selected;CBA[2].Selected;CBA[3].Selected;Field1;'
  51.    end;
  52.  
  53. end.
  54.  

It compiles and shows no runtime error, but my INI-file contains only:
Code: [Select]
[TApplication.Form1]
Form1_Top=344
Form1_Left=329
ColorBox1_Selected=32768
Form1_Field1=55

So it works for ColorBox1 (created by the object inspector) and for Field1 (integer variable), but not for array CBA[]. Can please somebody tell me what I am doing wrong? I attached a small demo project. Thanks in advance.
I use FPC 3.0.0 with Lazarus 1.6.2 on Windows 7.
« Last Edit: January 27, 2017, 04:14:12 pm by Hartmut »

Leledumbo

  • Hero Member
  • *****
  • Posts: 8833
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TIniPropStorage: how to add an array to my INI-file?
« Reply #1 on: January 26, 2017, 05:39:04 pm »
AFAIK TWhateverPropStorage relies on streaming, in which dynamically created components don't count. You will have to do saving and loading manually, using provided On(Save|Restore)ingProperties and (Read|Write)(Integer|String|Boolean|Rect|Strings), setting IniSection if you want.

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
Re: TIniPropStorage: how to add an array to my INI-file?
« Reply #2 on: January 26, 2017, 06:07:56 pm »
AFAIK TWhateverPropStorage relies on streaming, in which dynamically created components don't count.

If the dynamic array is the problem, I would prefer to use a normal array, but I cannot compile this:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
  9.  IniPropStorage, ColorBox;
  10.  
  11. type
  12.  ColorBoxArray = array[1..3] of TColorBox; // is 20 in my real program
  13.  { TForm1 }
  14.  
  15.  TForm1 = class(TForm)
  16.   ColorBox1: TColorBox;
  17.   IniPropStorage1: TIniPropStorage;
  18.   procedure FormCreate(Sender: TObject);
  19.  private
  20.    CB: ColorBoxArray;
  21.    FField1: Integer;
  22.  public
  23.  published
  24.    property CBA: ColorBoxArray read CB write CB;
  25.    property Field1: Integer read FField1 write FField1;
  26.  end;
  27.  
  28. var
  29.  Form1: TForm1;
  30.  
  31. implementation
  32.  
  33. {$R *.lfm}
  34.  
  35. { TForm1 }
  36.  
  37. procedure TForm1.FormCreate(Sender: TObject);
  38.    var i: integer;
  39.    begin
  40.    Field1:=55;
  41.    for i:=0 to High(CBA) do
  42.       begin
  43.       CBA[i]:=TColorBox.Create(self);
  44.       CBA[i].Top:=10;
  45.       CBA[i].Left:=i*120;
  46.       CBA[i].Parent:=self;
  47.       end;
  48.    Form1.SessionProperties:='Top;Left;ColorBox1.Selected;'
  49.      + 'CBA[1].Selected;CBA[2].Selected;CBA[3].Selected;Field1;'
  50.    end;
  51.  
  52. end.

I get an Error "This kind of property cannot be published" in line 24 (this error was the only reason why I switched to a dynamic array).
Does somebody have an idea how to compile with a normal array?

Leledumbo

  • Hero Member
  • *****
  • Posts: 8833
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TIniPropStorage: how to add an array to my INI-file?
« Reply #3 on: January 27, 2017, 05:54:59 am »
If the dynamic array is the problem, I would prefer to use a normal array, but I cannot compile this:
No, I said streaming, not dynamic array. Meaning the property you want to save/restore automatically must reside within the designed form, it cannot be anything you generate at runtime in memory. You can't escape from doing it manually.
I get an Error "This kind of property cannot be published" in line 24 (this error was the only reason why I switched to a dynamic array).
Does somebody have an idea how to compile with a normal array?
Static arrays, especially the one you created, cannot be published. As documented, its size is bigger than a pointer.

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
Re: TIniPropStorage: how to add an array to my INI-file?
« Reply #4 on: January 27, 2017, 04:13:50 pm »
Thanks a lot to Leledumbo for your help and the documentation link. Now I know why my static array didn't compile.

Here are the 2 recommended events which work fine:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.IniPropStorage1SavingProperties(Sender: TObject);
  2.    var i: integer;
  3.    begin
  4.    for i:=0 to High(CBA) do
  5.       IniPropStorage1.WriteInteger('CBA_' + IntToStr(i), CBA[i].Selected);
  6.    end;
  7.  
  8. procedure TForm1.IniPropStorage1RestoringProperties(Sender: TObject);
  9.    var i: integer;
  10.    begin
  11.    for i:=0 to High(CBA) do
  12.       CBA[i].Selected:=IniPropStorage1.ReadInteger('CBA_' + IntToStr(i),0);
  13.    end;  

After this my INI-file contains array CBA[] too:

Code: [Select]
[TApplication.Form1]
CBA_0=65280
CBA_1=65535
CBA_2=255
Form1_Top=344
Form1_Left=329
ColorBox1_Selected=16711680
Form1_Field1=55

 

TinyPortal © 2005-2018