Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi IdentMap funktioniert nicht (https://www.delphipraxis.net/138037-identmap-funktioniert-nicht.html)

blackdrake 2. Aug 2009 21:25


IdentMap funktioniert nicht
 
Hallo.

Ich habe eine Objekteigenschaft, die einen HKEY enthält. Leider kann diese im Objektinspektor nicht aufgelistet werden, da ein HKEY nicht im Bereich des Integers liegt.

Daher möchte ich TRegsitry ableiten, sodass ein "TRootKey" aufgelistet werden kann. Natürlich möchte ich die "Kompatibilität" zu den HKEYs behalten. Daher akzueptiert nun meine Ableitung die Werte $0000000x (Auflistungswerte für den OI) und $8000000x ("HKEY").

Leider funktioniert diese Auflistung einfach nicht. Ich habe mir schon alles von TColor abgeschaut, doch es klappt einfach nicht. Kompilierung funktioniert Problemlos. Aber im OI sehe ich nur die Zahl. Was kann ich tun?

Delphi-Quellcode:
unit Registry2;

// Registry2.pas von Daniel Marschall

// Der Typ HKEY ist ein vorzeichenloser 32-Bit und kann daher nicht mit einem
// TIdentMapEntry erfasst werden, da er nur vorzeichenbehaftete Integer
// akzeptiert. Daher können in VCLs die HKEYs nicht im Objektinspektor
// aufgelistet werden. Diese Ableitung behebt das Problem.

interface

uses
  Classes, Registry, Windows;

type
  TRootKey = LongWord;

  TRegistry2 = class(TRegistry)
  private
    function GetRootKey: TRootKey;
    procedure SetRootKey(Value: TRootKey);
  published
    property RootKey: TRootKey
      read GetRootKey write SetRootKey default HKEY_CURRENT_USER;
  end;

const
  RootKeys: array[0..6] of TIdentMapEntry = (
    (Value: HKEY_CLASSES_ROOT    - $80000000; Name: 'HLEY_CLASSES_ROOT'),
    (Value: HKEY_CURRENT_USER    - $80000000; Name: 'HKEY_CURRENT_USER'),
    (Value: HKEY_LOCAL_MACHINE   - $80000000; Name: 'HKEY_LOCAL_MACHINE'),
    (Value: HKEY_USERS           - $80000000; Name: 'HKEY_USERS'),
    (Value: HKEY_PERFORMANCE_DATA - $80000000; Name: 'HKEY_PERFORMANCE_DATA'),
    (Value: HKEY_CURRENT_CONFIG  - $80000000; Name: 'HKEY_CURRENT_CONFIG'),
    (Value: HKEY_DYN_DATA        - $80000000; Name: 'HKEY_DYN_DATA')
  );

function IdentToRootKey(const Ident: string; var RootKey: Longint): Boolean;
function RootKeyToIdent(RootKey: Longint; var Ident: string): Boolean;

implementation

function TRegistry2.GetRootKey: TRootKey;
begin
  if (inherited RootKey > $80000000) then
    result := inherited RootKey - $80000000
  else
    result := inherited RootKey;
end;

procedure TRegistry2.SetRootKey(Value: TRootKey);
begin
  if (Value < $80000000) then
    inherited RootKey := Value + $80000000
  else
    inherited RootKey := Value;
end;

function RootKeyToIdent(RootKey: Longint; var Ident: string): Boolean;
begin
  Result := IntToIdent(RootKey, Ident, RootKeys);
end;

function IdentToRootKey(const Ident: string; var RootKey: Longint): Boolean;
begin
  Result := IdentToInt(Ident, RootKey, RootKeys);
end;

initialization
  RegisterIntegerConsts(TypeInfo(TRootKey), IdentToRootKey, RootKeyToIdent);
end.
Wenn es fertig ist, möchte ich es natürlich in die CodeLib setzen.

PS: Meine vorherige Version arbeitete mit einem Aufzählungstyp, der schlicht und einfach die HKEY_* Symbole überschrieben hatte. Das blöde daran war, dass dadurch beim Anwender oftmals einen TRootKey <-> HKEY Compilerfehler entsteht. Deswegen möchte ich die Symbole nun nicht mehr überschreiben.

Gruß
blackdrake

himitsu 2. Aug 2009 21:47

Re: IdentMap funktioniert nicht
 
Auch wenn ich vermutlich nichts zum Problem direkt beitragen kann ... statt Bits zu ändern, würde ich einfach nur den LongWord (HKEY) in einen Integer casten

und dann als Integer, aber dennoch mit allen Bits, im OI anbieten.

Dann würden praktisch einfach nur alle Werte ab $80000000 in den negativen Bereich des Integers verschoben und es würde im Wert kein Bit verloren gehen, da ja in deiner aktuellen Ableitung $8000000x gleich $0000000x entspräche.



Delphi-Quellcode:
unit Registry2;

// Registry2.pas von Daniel Marschall

// Der Typ HKEY ist ein vorzeichenloser 32-Bit und kann daher nicht mit einem
// TIdentMapEntry erfasst werden, da er nur vorzeichenbehaftete Integer
// akzeptiert. Daher können in VCLs die HKEYs nicht im Objektinspektor
// aufgelistet werden. Diese Ableitung behebt das Problem.

interface

uses
  Classes, Registry, Windows;

type
  TRootKey = type LongInt;

  TRegistry2 = class(TRegistry)
  private
    function GetRootKey: TRootKey;
    procedure SetRootKey(Value: TRootKey);
  published
    property RootKey: TRootKey
      read GetRootKey write SetRootKey default TRootKey(HKEY_CURRENT_USER);
  end;

const
  RootKeys: array[0..6] of TIdentMapEntry = (
    (Value: Integer(HKEY_CLASSES_ROOT);    Name: 'HLEY_CLASSES_ROOT'),
    (Value: Integer(HKEY_CURRENT_USER);    Name: 'HKEY_CURRENT_USER'),
    (Value: Integer(HKEY_LOCAL_MACHINE);   Name: 'HKEY_LOCAL_MACHINE'),
    (Value: Integer(HKEY_USERS);           Name: 'HKEY_USERS'),
    (Value: Integer(HKEY_PERFORMANCE_DATA); Name: 'HKEY_PERFORMANCE_DATA'),
    (Value: Integer(HKEY_CURRENT_CONFIG);  Name: 'HKEY_CURRENT_CONFIG'),
    (Value: Integer(HKEY_DYN_DATA);        Name: 'HKEY_DYN_DATA')
  );

function IdentToRootKey(const Ident: String; var RootKey: Integer): Boolean;
function RootKeyToIdent(RootKey: Integer; var Ident: String): Boolean;

implementation

function TRegistry2.GetRootKey: TRootKey;
begin
  Result := TRootKey(inherited RootKey);
end;

procedure TRegistry2.SetRootKey(Value: TRootKey);
begin
  inherited RootKey := HKEY(Value);
end;

function RootKeyToIdent(RootKey: Integer; var Ident: String): Boolean;
begin
  Result := IntToIdent(RootKey, Ident, RootKeys);
end;

function IdentToRootKey(const Ident: String; var RootKey: Integer): Boolean;
begin
  Result := IdentToInt(Ident, RootKey, RootKeys);
end;

initialization
  RegisterIntegerConsts(TypeInfo(TRootKey), IdentToRootKey, RootKeyToIdent);
end.
[edit]
vielleicht hilft's ja, wenn man TRootKey als eigenständigen Typ definiert?

blackdrake 2. Aug 2009 22:03

Re: IdentMap funktioniert nicht
 
Hallo.

Das wäre in so fern vorteilhaft, da es dann nur 1 Lösung gäbe.

Andererseits verursacht dieser Code eine Compilerwarnung, sobald ein Benutzer einen HKEY_* (Typ HKEY = LongWord) aus der Windows.pas setzen will.

Delphi-Quellcode:
TRegistry2.Create.RootKey := HKEY_LOCAL_MACHINE;
würde also "Konstantenausdruck verletzt untere Grenze" verursachen. Auch wenn diese Warnung harmlos ist, kommt es für den Endanwender schon ein wenig seltsam rüber. Wenn ich eine Drittanbieterkomponente verwende und ich bei Benutzung Warnungen erhalte, muss ich davon ausgehen, dass entweder ich oder der VCL-Entwickler einen Fehler gemacht hat. Deswegen wäre das ein wenig verwirrend, oder?

Zu deinem Edit:

Delphi-Quellcode:
TRootKey = 0..4294967295; // LongWord
bringt leider keine Änderung. Es steht immer noch eine Zahl im OI und eigene Ident-Werte in String-Form werden nciht angenommen.

Gruß
blackdrake

blackdrake 2. Aug 2009 22:17

Re: IdentMap funktioniert nicht
 
(Nachtrag)

Hier ist die Testkomponente zur schnellen Rekonstruktion.

Delphi-Quellcode:
unit test;

interface

uses
  SysUtils, Classes, Windows;

type
  TRootKey = LongWord;

  TTest = class(TComponent)
  private
    FRootkey: TRootKey;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property RootKey: TRootKey read FRootKey write FRootKey default HKEY_CURRENT_USER;
  end;

const
  RootKeys: array[0..6] of TIdentMapEntry = (
    (Value: HKEY_CLASSES_ROOT    - $80000000; Name: 'HLEY_CLASSES_ROOT'),
    (Value: HKEY_CURRENT_USER    - $80000000; Name: 'HKEY_CURRENT_USER'),
    (Value: HKEY_LOCAL_MACHINE   - $80000000; Name: 'HKEY_LOCAL_MACHINE'),
    (Value: HKEY_USERS           - $80000000; Name: 'HKEY_USERS'),
    (Value: HKEY_PERFORMANCE_DATA - $80000000; Name: 'HKEY_PERFORMANCE_DATA'),
    (Value: HKEY_CURRENT_CONFIG  - $80000000; Name: 'HKEY_CURRENT_CONFIG'),
    (Value: HKEY_DYN_DATA        - $80000000; Name: 'HKEY_DYN_DATA')
  );

function IdentToRootKey(const Ident: string; var RootKey: Longint): Boolean;
function RootKeyToIdent(RootKey: Longint; var Ident: string): Boolean;

procedure Register;

implementation

constructor TTest.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  RootKey := HKEY_CURRENT_USER;
end;

procedure Register;
begin
  RegisterComponents('Beispiele', [TTest]);
end;

function RootKeyToIdent(RootKey: Longint; var Ident: string): Boolean;
begin
  Result := IntToIdent(RootKey, Ident, RootKeys);
end;

function IdentToRootKey(const Ident: string; var RootKey: Longint): Boolean;
begin
  Result := IdentToInt(Ident, RootKey, RootKeys);
end;

initialization
  RegisterIntegerConsts(TypeInfo(TRootKey), IdentToRootKey, RootKeyToIdent);
end.
Im OI steht dann 2147483649, aber keine DropDown-Box. Ident-Werte wie "HKEY_CURRENT_USER" werden als ungültig gekenneichnet. Weiß jemand, woran es liegt?

blackdrake 3. Aug 2009 17:54

Re: IdentMap funktioniert nicht
 
Hat denn keiner eine Ahnung, wieso es nicht funktioniert? Eine IdentMap dürfte doch bei der VCL-Entwicklung ein häufig verwendetes Instrument sein, oder? Mein Code aus dem vorherigen Post ist rekonstruiert das Problem exakt und benötigt lediglich die Registrierung.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:17 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz