unit Registry2;
{
Registry2.pas von Daniel Marschall, Version: 2009-08-03
(C) 2009 ViaThinkSoft.
Erweiterung der TRegistry, TRegIniFile und TRegistryIniFile, die die
Typsicherheit durch Zuhilfenahme der Aufzählungstypen THKEY und TRegAccess
verbessert. Dies kann auch Vorteilhaft sein, wenn diese Werte im
Objektinspektor aufgelistet werden sollen.
Das Problem bei TRegistry: Der Typ HKEY ist vom Typ Cardinal und kann daher
nicht mit einem TIdentMapEntry erfasst werden. Daher können in VCLs die
HKEYs nicht aufgelistet werden. Diese Ableitung behebt das Problem.
Anmerkung: Bei den Aufzählungstypen wurde kein "Unknown" Wert miteinbezogen.
Sollte ein unerwarteter Fall eintreten (z.B. neue Version der Windows.pas)
wird eine Exception ausgelöst.
Enthaltene Klassen
TRegistry2: Überschreibt alle HKEYs
TRegistry3: Überschreibt alle HKEYs und alle Registry-Access*
TRegIniFile: Überschreibt alle Registry-Access*
TRegistryIniFile: Überschreibt alle Registry-Access*
* Dies kann unter Umständen nicht erwünscht sein, da es sich nur auf die
grundlegenden Typen ALL, READ, WRITE und EXECUTE beschränkt.
(EXECUTE wird per Compilerschalter nicht mitberechnet, wenn READ mit
dem selben Wert definiert ist, so wie es bei Delphi 7 der Fall ist)
Kleines Manko bei TRegistry3: Das Symbol TRegistry3.Create(AAccess: LongWord)
ist weiterhin sichtbar. Dieses Symbol sollte daher nicht aufgerufen werden,
da hier Werte eingegeben werden können, die weder KEY_ALL_ACCESS,
KEY_READ/KEY_EXECUTE noch KEY_WRITE sind und deswege bei TRegistry3.GetAccess
eine EUnknownRegistryCase-Exception auslösen würde.
}
interface
uses
SysUtils, Classes, Registry, Windows;
{$IF KEY_READ <> KEY_EXECUTE}
{$DEFINE ADD_CASE_EXECUTE} // Derzeit ist dies der Fall
{$IFEND}
type
// siehe Windows.pas: HKEY_*
// Alle verfügbaren
THKEY = (hkClassesRoot, hkCurrentUser, hkLocalMachine,
hkUsers, hkPerformanceData, hkCurrentConfig, hkDynData);
// siehe Windows.pas: KEY_*
// Eine grobe Auswahl der wichtigen Elemente
TRegAccess = (raAll, raRead, raWrite
{$IFDEF ADD_CASE_EXECUTE}, raExecute
{$ENDIF});
EUnknownRegistryCase =
class(
Exception);
TRegistry2 =
class(TRegistry)
private
function GetRootKey: THKEY;
procedure SetRootKey(Value: THKEY);
function GetCurrentKey: THKEY;
protected
procedure ChangeKey(Value: THKEY;
const Path:
string);
function GetBaseKey(Relative: Boolean): THKEY;
function GetKey(
const Key:
string): THKEY;
procedure SetCurrentKey(Value: THKEY);
published
property CurrentKey: THKEY
read GetCurrentKey;
property RootKey: THKEY
read GetRootKey
write SetRootKey
{ default hkCurrentUser };
end;
TRegistry3 =
class(TRegistry2)
private
function GetAccess: TRegAccess;
procedure SetAccess(Value: TRegAccess);
public
constructor Create(AAccess: TRegAccess);
overload;
published
property Access: TRegAccess
read GetAccess
write SetAccess;
end;
TRegIniFile2 =
class(TRegIniFile)
public
constructor Create(
const FileName:
string; AAccess: TRegAccess);
overload;
end;
TRegistryIniFile2 =
class(TRegistryIniFile)
public
constructor Create(
const FileName:
string; AAccess: TRegAccess);
overload;
end;
implementation
type
KEY = LongWord;
resourcestring
LNG_UNKNOWN_CASE = '
Registry2.pas: An unknown %s value was found.';
function HKEY2ENUM(AHKEY: HKEY): THKEY;
begin
case AHKEY
of
HKEY_CLASSES_ROOT: result := hkClassesRoot;
HKEY_CURRENT_USER: result := hkCurrentUser;
HKEY_LOCAL_MACHINE: result := hkLocalMachine;
HKEY_USERS: result := hkUsers;
HKEY_PERFORMANCE_DATA: result := hkPerformanceData;
HKEY_CURRENT_CONFIG: result := hkCurrentConfig;
HKEY_DYN_DATA: result := hkDynData;
else
raise EUnknownRegistryCase.CreateResFmt(@LNG_UNKNOWN_CASE, ['
HKEY']);
end;
end;
function REGACCESS2ENUM(AAccess: KEY): TRegAccess;
begin
case AAccess
of
KEY_ALL_ACCESS: result := raAll;
KEY_READ: result := raRead;
KEY_WRITE: result := raWrite;
{$IFDEF ADD_CASE_EXECUTE}KEY_EXECUTE: result := raExecute;
{$ENDIF}
else
raise EUnknownRegistryCase.CreateResFmt(@LNG_UNKNOWN_CASE, ['
ACCESS']);
end;
end;
function ENUM2HKEY(AHKEY: THKEY): HKEY;
begin
result := HKEY_CURRENT_USER;
// Verhindert Compilermeldung
case AHKEY
of
hkClassesRoot: result := HKEY_CLASSES_ROOT;
hkCurrentUser: result := HKEY_CURRENT_USER;
hkLocalMachine: result := HKEY_LOCAL_MACHINE;
hkUsers: result := HKEY_USERS;
hkPerformanceData: result := HKEY_PERFORMANCE_DATA;
hkCurrentConfig: result := HKEY_CURRENT_CONFIG;
hkDynData: result := HKEY_DYN_DATA;
end;
end;
function ENUM2REGACCESS(AAccess: TRegAccess): KEY;
begin
result := KEY_ALL_ACCESS;
// Verhindert Compilermeldung
case AAccess
of
raAll: result := KEY_ALL_ACCESS;
raRead: result := KEY_READ;
raWrite: result := KEY_WRITE;
{$IFDEF ADD_CASE_EXECUTE}raExecute: result := KEY_EXECUTE;
{$ENDIF}
end;
end;
{ TRegistry2 }
function TRegistry2.GetRootKey: THKEY;
begin
result := HKEY2ENUM(
inherited RootKey);
end;
procedure TRegistry2.SetRootKey(Value: THKEY);
begin
inherited RootKey := ENUM2HKEY(Value);
end;
procedure TRegistry2.ChangeKey(Value: THKEY;
const Path:
string);
begin
inherited ChangeKey(ENUM2HKEY(Value), Path);
end;
function TRegistry2.GetBaseKey(Relative: Boolean): THKEY;
begin
result := HKEY2ENUM(
inherited GetBaseKey(Relative));
end;
function TRegistry2.GetKey(
const Key:
string): THKEY;
begin
result := HKEY2ENUM(
inherited GetKey(Key));
end;
procedure TRegistry2.SetCurrentKey(Value: THKEY);
begin
inherited SetCurrentKey(ENUM2HKEY(Value));
end;
function TRegistry2.GetCurrentKey: THKEY;
begin
result := HKEY2ENUM(
inherited CurrentKey);
end;
{ TRegistry3 }
constructor TRegistry3.Create(AAccess: TRegAccess);
begin
inherited Create(ENUM2REGACCESS(AAccess));
end;
procedure TRegistry3.SetAccess(Value: TRegAccess);
begin
inherited Access := ENUM2REGACCESS(Value);
end;
function TRegistry3.GetAccess: TRegAccess;
begin
result := REGACCESS2ENUM(
inherited Access);
end;
{ TRegIniFile2 }
constructor TRegIniFile2.Create(
const FileName:
string; AAccess: TRegAccess);
begin
inherited Create(FileName, ENUM2REGACCESS(AAccess));
end;
{ TRegistryIniFile2 }
constructor TRegistryIniFile2.Create(
const FileName:
string;
AAccess: TRegAccess);
begin
inherited Create(FileName, ENUM2REGACCESS(AAccess));
end;
end.