Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Einen resourcestring über einen String ansprechen (https://www.delphipraxis.net/161244-einen-resourcestring-ueber-einen-string-ansprechen.html)

bernau 24. Jun 2011 00:14

Delphi-Version: XE

Einen resourcestring über einen String ansprechen
 
Folgender Code(Schnipsel) ist vorhanden:

Delphi-Quellcode:
resourcestring
  AA_10_10='Dies ist ein Text';
  AA_10_11='Dies ist ein weiterer Text';
  AA_10_12='Dies ist noch ein Text';
  AA_10_13='Dies ist der letzte Text';
Ich möchte über eine Funktion den Wert auslesen und als String den Bezeichner übergeben.

Delphi-Quellcode:
 LabelXy.caption:=constantentext('AA_10_10');
LabelXy.caption sollte dan 'Dies ist ein Text' anzeigen.


Jemand eine Idee, wie ich das realsisieren kann?

himitsu 24. Jun 2011 07:11

AW: Einen resourcestring über einen String ansprechen
 
Geht nicht.

- Eine Resourcestring wird in den Resourcen als durchnummerierte Gruppen zu je 16 Strings abgelegt.
- Die Nummern/Indize der Resourcestrings werden bei jedem Neucompilieren "zufällig" (vermutlich in Compilier-/Linkreihenfolge) neu vergeben.
- Delphi speichert keine Variablen-/Konstantennamen.

> Erstell einfach mal eine EXE, mit deinen Ressourcestrings und schau mit einem Resourceeditor dort rein.

Lösung:
Selber die namentlichen "Text"-Resourcen erstellen (keine nummerierten Stringlisten, es sei denn du willst über die selbstvergebenen Nummern/Indize zugreifen)

ASM 24. Jun 2011 07:25

AW: Einen resourcestring über einen String ansprechen
 
Zitat:

Geht nicht.
Warum nicht so:
Code:
resourcestring
  AA_10_10='Dies ist ein Text';
  AA_10_11='Dies ist ein weiterer Text';
  AA_10_12='Dies ist noch ein Text';
  AA_10_13='Dies ist der letzte Text';

var ResStr: Array [0..3] of string =(AA_10_10,AA_10_11,AA_10_12,AA_10_13);

Function constantentext(i: word): String;
begin
 result:=ResStr[i] ;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 Label1.caption:=constantentext(random(3));
 // oder einfach nur (ohne spez.Function constantentext) : Label1.caption:=ResStr[random(3)];
end;

bernau 24. Jun 2011 07:56

AW: Einen resourcestring über einen String ansprechen
 
@himitsu: Danke für die Info. Ich habe es befürchtet :-(

@ASM: Das wird mir nichts bringen. Ich möchte ja speziell über den Namen der Konstante auf den Inhalt zugreifen und nicht über eine (nichtssagende) Indexnummer. Letztendlich werde ich auf ca. 50.000 verschiedene Strings zugreifen müssen. Dazu setze ich mir den Namen aus einer Berechung als String zusammen (AA_10_10 sind z.B. 3 zusammengesetzte Teilbereiche) und über diesen Namen Greife ich auf den Ressourcenstring zu.

Satty67 24. Jun 2011 08:17

AW: Einen resourcestring über einen String ansprechen
 
Bei 50.000 Resourcenstrings würde sich ja schon eher eine alternative Methode anbieten, wie eine Datenbank oder zumindest eine Key/Value Stringlist aus einer Text/XML-Datei.

Da wäre dann wenigsten auf einen Schlag die gewünschte Zugriffslogik ein Kinderspiel.

bernau 24. Jun 2011 12:14

AW: Einen resourcestring über einen String ansprechen
 
Ich fand es bisher immer gut, daß diese Daten in der EXE-Datei vorhanden waren. Eine externe Datei kommt für mich erst mal nicht in Frage.

Bisher hatte ich alle Strings in eine Procedure gepackt. Aber mit DelphiXE gibt's nun ein Problem.

Siehe: http://www.delphipraxis.net/158048-e...en-fehler.html

Jetzt muss ich mir was anderes einfallen lassen.

Luckie 24. Jun 2011 12:33

AW: Einen resourcestring über einen String ansprechen
 
Du kannst die XML Datei auch als Ressource in deine Exe eincompilieren und zur Laufzeit dann auf der Festplatte speichern. Ich würde sie dann in das temporäre Verzeichnis entpacken, denn da hast du auf alle Fälle Schreibrechte. Aber bitte bei Beendigung des Programms auch wieder löschen. Oder du erstellst ein Setup.

bernau 24. Jun 2011 13:08

AW: Einen resourcestring über einen String ansprechen
 
Zitat:

Zitat von Luckie (Beitrag 1108108)
Du kannst die XML Datei auch als Ressource in deine Exe eincompilieren und zur Laufzeit dann auf der Festplatte speichern. Ich würde sie dann in das temporäre Verzeichnis entpacken, denn da hast du auf alle Fälle Schreibrechte. Aber bitte bei Beendigung des Programms auch wieder löschen. Oder du erstellst ein Setup.

Das wäre natürlich eine Idee. Speichern muss ich die Datei wohl nicht. Kann ich doch bestimmt direkt in einen Stream einlesen. Ich werde mal "Suchen".

Danke:thumb:

jaenicke 24. Jun 2011 13:34

AW: Einen resourcestring über einen String ansprechen
 
TResourceStream --> TStringStream --> xmldoc.loadXml ;-)

ASM 24. Jun 2011 16:14

AW: Einen resourcestring über einen String ansprechen
 
Alternative ohne Verwendung eines externen Files zur Runtime
(in Anlehung an Julian M.Bucknall, 2001, "Tomes of Delphi: Algorithms and Data Structures"):

File ResStrings.inc:
Code:
CONST
cResStrBase = $5444;
maxResCount = 12;
AA_10_10  = cResStrBase + 0;
AA_10_11  = cResStrBase + 1;
AA_10_12  = cResStrBase + 2;
AA_10_13  = cResStrBase + 3;
AA_11_10  = cResStrBase + 4;
AA_11_11  = cResStrBase + 5;
AA_11_12  = cResStrBase + 6;
AA_11_13  = cResStrBase + 7;
AA_12_10  = cResStrBase + 8;
AA_12_11  = cResStrBase + 9;
AA_12_12  = cResStrBase + 10;
AA_12_13  = cResStrBase + 11;
{..usw..}
Resourcefile:
Code:
#include "ResStrings.inc"

STRINGTABLE
BEGIN
 AA_10_10, "Dies ist ein Text zu (10_10)"
 AA_10_11, "Dies ist ein Text zu (10_11)"
 AA_10_12, "Dies ist ein Text zu (10_12)"
 AA_10_13, "Dies ist ein Text zu (10_13)"
 AA_11_10  "Dies ist ein Text zu (11_10)"
 AA_11_11  "Dies ist ein Text zu (11_11)"
 AA_11_12  "Dies ist ein Text zu (11_12)"
 AA_11_13  "Dies ist ein Text zu (11_13)"
 AA_12_10  "Dies ist ein Text zu (12_10)"
 AA_12_11  "Dies ist ein Text zu (12_11)"
 AA_12_12  "Dies ist ein Text zu (12_12)"
 AA_12_13  "Dies ist ein Text zu (12_13)"
 {..usw..}
END
Compile Resource:
Code:
brcc32.exe ResStrings.rc
Projektfile:
Code:
{...}

implementation

{$R *.dfm}
{$R ResStrings.res}
{$I ResStrings.inc}

type
  tArrResStr = array of string;

var
  ArrResStr: tArrResStr;

// an die Logik der Bezeichnung der Elemente des Arrays anpassen !
// hier zum konkreten Beispiel der verwendeten Stringtable
procedure PrepareArray(var Arr: tArrResStr);
var
  i, j, z, basis: integer;
begin
  setlength(Arr, maxResCount);
  basis := 10;
  z := basis;
  j := 0;
  for i := Low(Arr) to High(Arr) do
  begin
    case i of
      0: ;
      4:
        begin
          inc(z, 1);
          j := 0;
        end;
      8:
        begin
          inc(z, 1);
          j := 0;
        end;
      {...}
    else inc(j);
    end;
    Arr[i] := format('AA_%2.d_%2.d', [z, basis + j]);
  end;
end;

procedure ClearArray(var Arr: tArrResStr);
begin
  setlength(Arr, 0);
end;

function IndexOf(Arr: tArrResStr; const item: string): Integer;
var
  i: Integer;
begin
  Result := -1;
  for i := Low(Arr) to High(Arr) do
  begin
    if AnsiSameText(item, Arr[i]) then
    begin
      Result := i;
      Break;
    end;
  end;
end;

function constantentext(ResConst: word): string; overload;
begin
  setlength(result, 255);
  LoadString(hinstance, ResConst, pchar(result), 255);
end;

function constantentext(ResConstName: string): string; overload;
var
  ResConst: Word;
begin
  ResConst := IndexOf(ArrResStr, ResConstName);
  result := pchar(constantentext(cResStrBase + ResConst));
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  PrepareArray(ArrResStr);
  // Beispiel der Übergabe per Indexkonstante als String
  Label1.caption := constantentext('AA_10_10');
  Label2.caption := constantentext('AA_11_13');
  // Beispiel der Übergabe unmittelbar als Indexkonstante
  Label3.caption := constantentext(AA_12_12);
  ClearArray(ArrResStr);
end;
Da zur Compiletime die Logik der in der Stringtable vergebenen Indexkonstanten feststeht, muss allein die Zuordung der Namen dieser Indexkonstanten zu den Strings des entspr. Arrays mit Hilfe einer Funktion PrepareArray() ausgearbeitet werden.
Dies ist die eigentliche Aufgabe der Anpassung an das konkrete Projekt. Jedoch dürfte die Ausarbeitung dieser Funktion wohl keine ernsthaften Probleme machen, wenn die Namen der Indexkonstanten nach einem logischen Prinzip vergeben werden, welches dann wiederum in dieser Funktion umgesetzt wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:26 Uhr.

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