0

After I added too many user defined values to my application, I had to develop something like below. And now, it is getting complex. I do not want to keep developing this tool. At least, I would like to compare my tool's properties to other solutions.

So, I wonder if there is a generic solution for this kind of job. I googled but I do not know right keywords for this approach (I use Delphi 6. I can read C++ and C#).

My goal is,

  • Avoid coding user defined parameter definition
  • Avoid coding user defined parameter user interface and coding business rule
  • In code, accessing parameter as if strictly defined (not like this: GetParameter('parameter_name_str'))
  • In code, accessing parameter without type casting from a generic type

--

Okay, I wrote a tool program. By using it, one can produce xml files like this:

    <?xml version="1.0"?>
    <parameters>
      <parameter id="PrinterEnable">
        <description>Select yes to use printer.</description>
        <group>Printer Settings</group>
        <title>Enable Your Printer</title>
        <type>boolean</type>
      </parameter>
      <parameter id="PrinterConnection">
        <description>You can refer to your printer's manuel to select correct cable.</description>
        <group>Printer Settings</group>
        <title>How to connect your printer</title>
        <type>list</type>
        <items>
          <item value="1">Usb</item>
          <item value="2">Serial</item>
          <item value="3">Parallel</item>
        </items>
      </parameter>
      <parameter id="PrinterWidth">
        <description>Enter width of paper to use in millimeters</description>
        <group>Printer Settings</group>
        <title>Paper Width</title>
        <type>integer</type>
        <default>25</default>
        <min>20</min>
        <max>200</max>
      </parameter>
    </parameters>

Then, same tool, automatically creates two files: A Delphi rc file includes a referance to above xml file and (after ask me a few question like class name, unit name) another Delphi pas unit file like this below :

    unit AppParameters;

    interface

    uses
      libParameters3;

    type
      TAppParameters =class(TParameters3)
      private
        FFileName :string;
      public
        constructor Create;
        procedure Load;
        procedure Save;
            function PrinterEnable: Boolean;
        function PrinterConnection: Integer;
        function PrinterWidth: Integer;
      end;

    implementation

    uses
      Classes, Forms, SysUtils, Windows;

    { AppParameters }

    constructor TAppParameters.Create;
    var
      AStream :TResourceStream;
    begin
      AStream :=TResourceStream.Create(HInstance, 'APP_PARAMETERS', RT_RCDATA);
      try
        inherited LoadDefFromStream(AStream);
      finally
        AStream.Free;
      end;

      FFileName :=ChangeFileExt(Application.ExeName, '.ini');
    end;

    procedure TAppParameters.Load;
    var
      AFileStream :TFileStream;
    begin
      AFileStream :=TFileStream.Create(FFileName, fmOpenRead or fmShareDenyWrite);
      try
        LoadValFromStream(AFileStream);
      finally
        AFileStream.Free;
      end;
    end;

    procedure TAppParameters.Save;
    var
      AFileStream :TFileStream;
    begin
      AFileStream :=TFileStream.Create(FFileName, fmCreate or fmShareDenyWrite);
      try
        SaveValToStream(AFileStream);
      finally
        AFileStream.Free;
      end;
    end;

    function TAppParameters.PrinterEnable: Boolean;
    begin
      Result :=GetParameter('PrinterEnable').AsBoolean;
    end;

    function TAppParameters.PrinterConnection: Integer;
    begin
      Result :=GetParameter('PrinterConnection').AsInteger;
    end;

    function TAppParameters.PrinterWidth: Integer;
    begin
      Result :=GetParameter('PrinterWidth').AsInteger;
    end;

    end.

After all, in Delphi on my real code, I can use it like this below:

    procedure TForm1.FormCreate(Sender: TObject);
    var
      AWidth :integer;
    begin
      FAppParameters :=TAppParameters.Create; //defined in TForm1 private

      FAppParameters.Load;
      if FAppParameters.PrinterEnable then begin
        case FAppParameters.PrinterConnection of
          1 : begin end; {Do Usb}
          2 : begin end; {Do Serial}
          3 : begin end; {Do Parallel}
        end;

        AWidth :=FAppParameters.PrinterWidth;
        //Do something with AWidth
      end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Form2 :=TForm2.Create(Self);
      try
        Form2.Caption :='Options';
        FAppParameters.PopulateEditor(Form2, Form2);
        Form2.ShowModal;
      finally
        Form2.Free;
      end;
    end;
Blorgbeard
  • 101,031
  • 48
  • 228
  • 272
  • 2
    You could easily serialize any class to json or xml using RTTI if you had a more modern version of Delphi. – LU RD Nov 14 '17 at 19:46
  • So should I search it as "serialization" ? – Ömür Ölmez Nov 14 '17 at 20:02
  • 2
    Yes, but D6 is limited in its reflection capacities. Some help in this Q [How to save an object to a file in Delphi](https://stackoverflow.com/q/3750072/576719). – LU RD Nov 14 '17 at 20:08

1 Answers1

0

As you don't mention XML as a constraint and use Delphi 6, I'd like to propose to use the Windows registry instead with standard TRegistry class. The Windows registry is the hierarchical database to store application settings.

uses
  SysUtils, Windows, Registry, Forms;

procedure SaveFormLayout(const AForm: TForm);
var
  R: TRegistry;
begin
  R := TRegistry.Create;
  try
    R.RootKey := HKEY_CURRENT_USER; // HKEY_LOCAL_MACHINE requires admin rights
    R.OpenKey('My Software\Forms\' + AForm.Name, true);
    R.WriteInteger('Top', AForm.Top);
    R.WriteInteger('Left', AForm.Left);
    R.WriteInteger('Height', AForm.Height);
    R.WriteInteger('Width', AForm.Width);
    R.WriteInteger('WindowState', integer(AForm.WindowState));
    R.CloseKey;
  finally
    R.Free;
  end;
end;

Registry settings can be easily exported into the file and then imported with REGEDIT or REG command line Windows utilities so you can migrate user profile like a file copy.

serge
  • 992
  • 5
  • 8
  • I cold not explain what I am searching for or I discovered something new. In your example, * You should code twice every string of first parameters (ie 'Top'). One for WriteInteger, one for ReadInteger. * You should also create user interface of that parameter so user can edit the values. * You should also code some control logic ie what if user entered string for 'Top' parameter rather than an integer number. In my program, there are over 50 parameters since I started developing. I do not want to add manually another 90 parameters. – Ömür Ölmez Nov 17 '17 at 18:07
  • Sorry, I should first thank you for your interest and example you gave. – Ömür Ölmez Nov 17 '17 at 18:08