Scenario: in your Delphi applications you have a configuration form you use to let the user change various parameters the application requires, like: database connection parameters, color of focused input controls, default printer and alike.
Such a configuration ("Options") form is mostly always created on the fly (at run-time) and displayed modally.
When the form is created you populate all the edit controls (TEdit, TComboBox, TMemo, ...) from some configuration storage medium (Registry, Ini, Database, etc.).
Such a configuration screen might host "Cancel" and "Apply" buttons. The task of the "Cancel" button would be to revert all the changes back to the initial values.
The idea of this article is to show you how to implement such a "revert back" mechanism in your Delphi application.
The Cancel Changes "Magic Button"
We need a way of storing "original" values contained in the various TCustomEdit descendants, that is, in their Text property. A TStringList type variable is an ideal candidate for the job as it can host a "collection" of strings where each string is associated with an object.In our scenario, a string in a string list is the value of the Text property of a TCustomEdit and the associated object is the TCustomEdit itself.
First, declare a TStringList form-level variable:
type
TConfigForm = class(TForm)
...
private
fEditOriginals : TStringList;
procedure PopulateEditOriginals;
property EditOriginals : TStringList read fEditOriginals;
Store Values
In the Form's OnCreate event, create the "EditOriginals" string list and after you fill in the edit controls with configuration values, populate the "EditOriginals" list:procedure TConfigForm.FormCreate(Sender: TObject) ;The PopulateEditOriginals procedure iterates through the Components property of the form. The Components property lists all components owned by the component. Since the form is the owner of all the design-time dropped components on it, we use Components to get all the TCustomEdit descendants on the form.
begin
fEditOriginals := TStringList.Create;
//fill in edits with some existing "configuration" data
Edit1.Text := 'Delphi';
Edit2.Text := 'Rules';
LabeledEdit1.Text := 'CodeGear';
Memo1.Text := 'Borland in Memo';
//fill in initial values
PopulateEditOriginals;
end;
procedure TConfigForm.PopulateEditOriginals;
var
c : integer;
begin
for c := 0 to -1 + ComponentCount do
begin
if Components[c] is TCustomEdit then
begin
EditOriginals.AddObject(TCustomEdit(Components[c]).Text, Components[c]) ;
end;
end;
end;
The AddObject method of the TStringList adds the value of the Text property the string list "EditOriginals", and associates the component with the string.
Since we are interested only in those components that are descendants of TCustomEdit (TEdit, TMemo, TLabeledEdit, etc), using some type checking / casting ensures only such controls are stored in the "EditOriginals" list.
Cancel Changes
When the "Cancel Changes" button is clicked we want to revert back to the original values:procedure TConfigForm.CancelButtonClick(Sender: TObject) ;This part is simple. Iterate through the "EditOriginals" list. Cast the object to a TCustomEdit and assign its Text property the "original" value.
var
c : integer;
begin
for c := 0 to -1 + EditOriginals.Count do
begin
TCustomEdit(EditOriginals.Objects[c]).Text := EditOriginals[c];
end;
end;
Apply Changes
If at any point you want to change the "current" original values, that is "Apply changes", you can simply update the strings in the "EditOriginals" list:procedure TConfigForm.ApplyButtonClick(Sender: TObject) ;
var
c : integer;
begin
for c := 0 to -1 + EditOriginals.Count do
begin
EditOriginals[c] := TCustomEdit(EditOriginals.Objects[c]).Text;
end;
end;
Finally, make sure you free the list once you are done using the configuration form, do it in the OnDestroy event handler:
procedure TConfigForm.FormDestroy(Sender: TObject);
begin
//free string list
//no need to free objects
//they are owned by the form
FreeAndNil(fEditOriginals) ;
end;
That's all. Make sure you download the code. Change the text in the edit boxes, then hit "Cancel" It's working! :)


