-1

I would like my application to remember which selected row in the database table was used (selected) before the application got closed and then load it (have it selected) the next time the application starts.The table has only 4 records and is read only so I dont have to worry if someone tries to change anything. Right now I use :

procedure TForm3.ClientDataSet1AfterOpen(DataSet: TDataSet);
begin
  Clientdataset1.DisableControls;
  try
    cxGrid1DBTableView1.DataController.KeyFieldNames := 'ID';
    cxGrid1DBTableView1.DataController.LocateByKey('4');
  finally
    Clientdataset1.EnableControls;
  end;
end;

But this is hardcoded. I want it flexible. How can I save these settings to an ini file located in the application.exe folder and load them when the application starts ? So ,for example,if key was '3' (when the app. exited) I load it the next time.

TLama
  • 75,147
  • 17
  • 214
  • 392
user763539
  • 3,509
  • 6
  • 44
  • 103
  • 3
    If you load the value in `TDataset.OnAfterOpen` then you should save the value in `TDataset.OnBeforeClose` ;o) – Sir Rufo Jan 09 '14 at 08:09
  • First separate your data out of the form. Use DataModule. On the datamodule you have an Oncreate and an onDestroy. On these event you can use the TRegistryIniFile to store and save the params. – Ravaut123 Jan 09 '14 at 08:10
  • I dont want to use registry. – user763539 Jan 09 '14 at 08:48
  • I'd say what @Sir Rufo suggests is the right way. Saving and loading from an INI file is so trivial that doesn't need to be addressed here I think. – TLama Jan 09 '14 at 09:04
  • 2
    Place ini file into %AppData% path. However using registry is simpler: you would not think where to place the file, so it would not end in read-only folder – Arioch 'The Jan 09 '14 at 10:05
  • TLama, I have never used ini files before. But, it's no problem....plenty of examples around. What I dont know is how to save the grid view to ini and back. – user763539 Jan 09 '14 at 10:15
  • 3
    @user763539 you don't need to save grid view, you sould save selected row `ID` (primary key) – teran Jan 09 '14 at 10:45
  • It seems theres an eror here ; ....AsString ), [] ); The comma is giving an error.... – user763539 Jan 09 '14 at 11:39
  • Placing the Application INI in the same directory of your application.exe is asking for troubles! I suggest you take the time and learn about UAC... – kobik Jan 09 '14 at 12:01
  • 1
    @Ravaut123, datamodule.OnCreate is not the right event to do this. it does not guaranty that the DataSet is already opened. I would also use a Flag (e.g. DataSet.Tag) with the `DataSet1AfterOpen` to indicate that it is the first time it's opened because it could be opened/closed several time during the application life-time. – kobik Jan 09 '14 at 12:13
  • ini files are simple. More trouble with registry (uac). – user763539 Jan 09 '14 at 12:29
  • @kobik that is not about UAC at all, that is about normal setup of Windows NT/2000/XP/Vista... - Any Windows except 95/98/ME and higher than reduced Home/Starter editions. `Program Files` are not to be written by non-admin users. Actually UAC makes it easier, as it comes along with FS virtualization in Vista+ – Arioch 'The Jan 09 '14 at 12:59
  • "More trouble with registry (uac)" what ? in which place of registry did you tried to save it ? in protected system-only ? put the values in HKCU/Software/YourName/YourProgramName – Arioch 'The Jan 09 '14 at 13:00

1 Answers1

4

Use the TDataSet.OnAfterOpen and TDataSet.OnBeforeClose events to load and save the desired values

procedure TForm3.ClientDataSet1AfterOpen(DataSet: TDataSet);
var
  LIni : TIniFile;
begin
  DataSet.DisableControls;
  try
    LIni := TIniFile.Create( '<YourIniFileName.ini>' );
    try
      DataSet.Locate( 'ID', LIni.ReadString( 'MyDataSet', 'ID', '' ), [] );
    finally
      LIni.Free;
    end;
  finally
    DataSet.EnableControls;
  end;
end;

procedure TForm3.ClientDataSet1BeforeClose(DataSet: TDataSet);
var
  LIni : TIniFile;
begin
  LIni := TIniFile.Create( '<YourIniFileName.ini>' );
  try
    LIni.WriteString( 'MyDataSet', 'ID', DataSet.FieldByName( 'ID' ).AsString ) );
  finally
    LIni.Free;
  end;
end;

This is a very simple and straight forward sample and you should not implement this in real applications.

In real applications you will delegate this to a singleton that takes care of reading and writing such application values

// Very simple KeyValue-Store
IKeyValueStore = interface
  function GetValue( const Key : string; const Default : string ) : string;
  procedure SetValue( const Key : string; const Value : string );
end;

// Global Application Value Store as Singleton   
function AppGlobalStore : IKeyValueStore;

and gives you a very smart solution

procedure TForm3.ClientDataSet1AfterOpen(DataSet: TDataSet);
begin
  DataSet.DisableControls;
  try
    DataSet.Locate( 'ID', AppGlobalStore.GetValue( 'MyDataSet\ID', '' ), [] );
  finally
    DataSet.EnableControls;
  end;
end;

procedure TForm3.ClientDataSet1BeforeClose(DataSet: TDataSet);
begin
  AppGlobalStore.SetValue( 'MyDataSet\ID', DataSet.FieldByName( 'ID' ).AsString ), [] );
end;
Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
  • @kobik i did those singletons as class properties without creating an actual object :-) – Arioch 'The Jan 09 '14 at 13:01
  • @Sir Rufo - cant compile your "LIni.WriteString( 'MyDataSet', 'ID', DataSet.FieldByName( 'ID' ).AsString ), [] );" Delphi compiler does not digest the last comma.... – user763539 Jan 10 '14 at 11:59