System Delphi

Title: Personal settings and the windows registry
Question: What is the structure of the registry?
What settings to store in the registry, how to do so?
Answer:




Registry
Registry
Scope
This article is the third article in a series of four articles about personal
settings. This article deals with the usage of the registry for retaining
personal settings. It explains the working of the registry, how to read
& write date in the registry from Delphi, and contains an example:
a form which reads its previous position on the screen.
One thing every application i.m.h.o. should contain is a registration
in the registry -the registry should have a clue in which directory your
application has been stored. You may choose to have this handled by your
installtion program, which is a logical place to do so. But the program
can also do it itself, so that the user moving the directory with your
application from the windows explorer can fix its own settings by simply
starting your program.
The registry - its structure
The registry was introduced by Microsoft with Windows 95. In Windows 95
and Windows 98, there are 2 files in your windows directory called user.dat
and system.dat which contain the data in your registry. However, in all
cases Microsoft provides a utility regedit to browse and change the registry.
When you use this tool to open your registry, you will see 5 base keys:
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFIGURATION
These five keys are identical in all window versions. Each one has many
subkeys, which in turn have subkeys again. The registry has a strict hierarchical
structure. For our purpose only 2 of them are interesting: HKEY_CURRENT_USER
and HKEY_LOCAL_MACHINE. The first is, as the name suggests, user dependant,
the second is applicable to all the machine. You might think this key contains
just hardware related data, but it has a subkey for software as well. The
local machine root is a good choice for items applicable to all users.
Reading data
The reading of data from the registry is illustrated with an example. We
will cerate a new form which will remember its previous location on the
screen. The location is determined by the Top and Left properties of the
form. In addition to these, we will read and store the Height and Width
properties of the form.
const
cKey = 'SOFTWARE\Test_Company\Test_Application';
// key where item values will be stored and read

procedure TRememberForm.FormCreate(Sender:
TObject);
var
lReg: TRegistry;
getInt: integer;
begin
inherited;
// general purpose:
// read latest Left,
Top, Width and Height
lReg := TRegistry.Create;
// create registry object
lReg.RootKey := HKEY_CURRENT_USER;
// set root to current user root,

// to ensure different users on this

// machine have their own setting
lReg.OpenKey(cKey, True);
// Open key where we will read items
if lReg.ValueExists(self.name +
'.Left') then // check if
value for item formname.left exists
begin
getint := lReg.ReadInteger(self.name
+ '.Left'); // Read left position of actual form
if getint 0 then
self.Left := getint;
end;
if lReg.ValueExists(self.name +
'.Top') then
begin
getint := lReg.ReadInteger(self.name
+ '.Top');
if getint 0 then
self.Top := getint;
end;
if lReg.ValueExists(self.name +
'.Width') then
begin
getint := lReg.ReadInteger(self.name
+ '.Width');
if getint 0 then
self.Width := getint;
end;
if lReg.ValueExists(self.name +
'.Height') then
begin
getint := lReg.ReadInteger(self.name
+ '.Height');
if getint 0 then
self.Height :=
getint;
end;
// Close and free
lReg.CloseKey;
lReg.Free;
end;
Let's have a short look at the main points:
lReg := TRegistry.Create;
// create registry object
This line creates the Registry object.
lReg.RootKey := HKEY_CURRENT_USER;
// set root to current user root,

// to ensure different users on this

// machine have their own setting
We set the root to indicate in which of the 5
roots we want to work. HKEY_CURRENT_USER is the default value. Alternately,
we might have chosen HKEY_LOCAL_MACHINE if we wanted to save settings for
all users on this machine.
lReg.OpenKey(cKey, True);
// Open key where we will read items
The key where items will be stored and read is
opened. If the key does not exist, windows automatically creates it. Note
that capitalization is important when the registry key is created. Most
entries in the registry have first letter uppercase and the rest lowercase,
and it is good practice to comply.
if lReg.ValueExists(self.name + '.Left')
then
// check if value
for item formname. left exists
This statement tests if the item FormName.left
exists within the open key.
begin
getint := lReg.ReadInteger(self.name
+ '.Left'); // Read left position of actual form
As an alternative for ReadInteger, the TRegistry
object also provides functions to read strings, booleans, dates, datetimes,
times, floats, and binary data.
if getint 0 then
self.Left := getint;
end;
By putting all these code in the FormCreate, the
window is automatically positioned at the right spot at creation. Of course
the code above can not be really tested when we don't have any data, so
the next step is to write these items in the FormDestroy.
Writing data
The FormDestroy event is a good moment to write the data to the registry.
The code is a lot shorter:
procedure TRememberForm.FormDestroy(Sender : TObject);
var
lReg : TRegistry;
begin
// open registry, set root and key
lReg := TRegistry.Create;
lReg.RootKey := HKEY_CURRENT_USER;
lReg.OpenKey(cKey, True);
// write last Left, Top, Width and Height
lReg.WriteInteger(self.name + '.Left', self.Left);
lReg.WriteInteger(self.name + '.Top', self.Top);
lReg.WriteInteger(self.name + '.Width', self.Width);
lReg.WriteInteger(self.name + '.Height', self.Height);
// close all
lReg.CloseKey;
lReg.Free;
inherited;
end;
As with reading data, the same applies with writing data. You can
easily write booleans, currencies, dates, datetimes, floats, strings and
times, and binary data. In addition, there is a WriteExpandString, which
is meant for unexpanded strings with "%" in it, such as "Open file %s failed".
WriteInteger creates a name when the name does not yet exist. If a write
operation fails, an exception is raised.
Alternatives
There are 2 other objects, TRegIniFile and TRegistryInifile available.
TRegistryIniFile presents a simple interface to the system registry
and hides the need to know about the underlying structure of the registry.
TRegistryIniFile enables handling the Windows system registry as if it
were a Windows 3.x INI file. Instead of processing an INI file, however,
TRegistryIniFile reads from and writes to the system registry.
TRegIniFile presents a simple interface to the system registry, hiding
the need to know about the underlying structure of the registry. TRegIniFile
acts as a helper object to TRegistryIniFile.
Personally I avoid using these 2 classes. The programmer saves some
time by not having to understand the registry. But the structure of the
registry is rather straightforward hierarchical, and using the registry
as if it was an ini-file limits its usage.
Limitations and final words
There are a few limitations which we haven't discussed. First, The registry
is not meant a a database for storing vast quantities of data. It is meant
for storing initialization and configuration data. Anything over 2Kb had
better be stored in a separate file. If you wish, you can mention the corresponding
file location in the registry. Then WriteBinary is especially useful for
storing recordtypes. Using a record type saves you typing code, and it
can be written to and read from the registry with 1 statement, saving both
time and storage. And a large registry might slow down all applications.
There is a small bug in the MoveKey procedure under WNT. It should move
a key including Subkeys, but it does not, at least not in D2-4. In the
help of Delphi 5 this problem has been documented. The problem does not
seem to appear under W2K.
Third, it seems Windows NT & Windows 2000 administrators can limit
Registry access. Using the registry may conflict with IT-policies in some
companies.
Should you like the form we created, right click on the form and choose
'add to repository'. You can then create descendants by choosing File /
New / forms.