![]() |
Problem mir StringResourcen...
Ich habe in meinem Hauptprogramm und in div. Sprach-dll's Stringresourcen untergebracht und gebe dem User die Möglichkeit über eine Exportfunktion die aktuellen Sprachresourcen zu exportieren und da fangen meine Probleme an...
Das schreiben der rc an sich ist kein Problem, ich schreibe die Werte mit einer Schleife in die entspr. Datei, dabei durchlaufe ich einfach alle Werte von 0 bis... und das weiß ich eben nie genau :roll: ... Bisher muß ich die bettr. Scheife nach jeder Resourcenanpassung von Hand anopassen, dass nun auch die neuen Texte berücksichtigt werden :? Kann man irgendwie herausfinden, ob eine Textresource mit einem bestimmten Index vorhanden ist? |
Re: Problem mir StringResourcen...
Ich hab jetzt mal eine Funktion geschrieben, die mir eigentlich den höchsten Index liefern sollte...
Delphi-Quellcode:
Diese Funktion tut es allerdings nicht, weil GetLastError offensichtlich sehr unzuverlässig ist :evil: :roll:
function GetMaxResID: integer;
var Buffer: array[0..MAX_PATH] of Char; n: integer; begin for n := 0 to 9999 do begin if Loadstring(hinstance, n, @buffer, MAX_PATH) = 0 then begin if GetLastError <> ERROR_SUCCESS then break else Result := n; end else Result := n; end; end; Die Funktion liefert mir bei realen 163 Strings "abwechselnd" (unregelmäßig) 162 (korrekt) und 175 :gruebel: |
Re: Problem mir StringResourcen...
:shock: ... warum benutzt du nicht:
![]() |
Re: Problem mir StringResourcen...
Zitat:
|
Re: Problem mir StringResourcen...
Sicher?
Zitat:
|
Re: Problem mir StringResourcen...
Sicher!
Codeauszug
Delphi-Quellcode:
EnumResourceNamesProc wird bei mir ganze 38 mal aufgerufen, obwohl allein meine eigenen Stringresourcen schon 162 Durchläufe auslösen sollten :gruebel: ...
function GetMaxResID: integer;
function EnumResourceNamesProc(Module: HMODULE; ResType: PChar; ResID: Integer; lParam: TStringList): Integer; stdcall; function Fill(Wert: string): string; begin Result := Wert; while Length(Result) < 6 do Result := '0' + Result; end; var ResourceName: string; begin lParam.Add(Fill(IntToStr(lParam.Count)) + '-' + Fill(IntToStr(ResID))); Result := 1; end; var Buffer: array[0..MAX_PATH] of Char; n: integer; MyList: TStringList; begin n := 0; MyList := TStringList.Create; MyList.Sorted := True; windows.EnumResourceNames(hinstance, RT_STRING, @EnumResourceNamesProc, Integer(MyList)); for n := 0 to MyList.Count - 1 do showmessage(MyList[n]); |
Re: Problem mir StringResourcen...
Moin FriFra,
eine Stringresource kann bis zu 16 Strings umfassen. Dadurch erklärt sich wohl die Differenz. [EDIT] Und ich hab' sogar den Link zu meinem alten Thread wiedergefunden: ![]() [/EDIT] |
Re: Problem mir StringResourcen...
Diesen Tread hatte ich auch schon gelesen und auch umgesetzt... Das Problem habe ich trotzdem noch.
Selbst wenn ich mit EnumResourceNames alle Resourcen ermittle und versuche jede "Teilresource" zu laden um bei einem möglichen Fehler (nicht vorhanden) abzubrechen liefert mir GetLastError trotz definitiv nicht vorhandener ID ein ERROR_SUCCESS, deshalb komme ich auch so auf 175 statt 163 :roll: Testcode:
Delphi-Quellcode:
Wobei es effektiv völlig egal wäre, ob ich mit EnumResourceNames arbeite oder einfach nur "blind" versuchen würde alle Strings mit den IDs von 0 - 9999 zu laden... würde GetLastError funktionieren, tut es aber nicht, deshalb liefern beide Versionen ein falsches Ergebnis, wobei die vorherige Version bei mir wenigstens sporadisch das richtige Ergebnis lieferte :roll:
function GetMaxResID: integer;
function EnumResourceNamesProc(Module: HMODULE; ResType: PChar; ResID: Integer; lParam: TStringList): Integer; stdcall; function Fill(Wert: string): string; begin Result := Wert; while Length(Result) < 6 do Result := '0' + Result; end; var i: integer; Buffer: array[0..MAX_PATH] of Char; begin for i := (ResID - 1) * 16 to ResID * 16 do begin if LoadString(hinstance, i, @buffer, MAX_PATH) = 0 then begin if GetLastError <> ERROR_SUCCESS then break; end; lParam.Add(Fill(IntToStr(i { + ((ResId - 1) * 16)}))) end; Result := 1; end; var Buffer: array[0..MAX_PATH] of Char; n: integer; MyList: TStringList; begin n := 0; MyList := TStringList.Create; MyList.Sorted := True; windows.EnumResourceNames(hinstance, RT_STRING, @EnumResourceNamesProc, Integer(MyList)); if (MyList.Count > 0) and (StrToIntDef(MyList[0], -1) = 0) then begin Result := 0; for n := 1 to MyList.Count - 1 do begin if StrToIntDef(MyList[n], -1) = StrToIntDef(MyList[n - 1], -1) + 1 then Result := n else break; end; end else Result := 0; MyList.Free; end; |
Re: Problem mir StringResourcen...
Hallo FriFra,
funktioniert das bei dir?
Delphi-Quellcode:
D7 kam übrigens mit einer Demo für einen Resource Explorer - vielleicht gibt es den auch noch unter D2005?
// funktioniert nur bei fortlaufender ID
function GetMaxStringID(start: integer): integer; begin Result := start; while SysUtils.LoadStr(Result) <> '' do Inc(Result); if Result = start then Result := -1 else Result := Result - 1; end; Grüße vom marabu |
Re: Problem mir StringResourcen...
Das ist keine Lösung, da es auch gültige Stringresourcen geben kann die einen leeren String enthalten ;) und da wäre dann frühzeitig schluß :? ...
P.S.: Die "leeren" strings kommen ganz einfach zu stande, wenn in z.B: ein Control aus meinem Programm entferne und ich die Caption/den Text vorerst nicht mehr benötige, dann mache ich diesen Text leer, um ihn bei der nächsten Gelegenheit für etwas anderes zu nutzen (wäre er nicht leer, würde ich den Überblick verlieren). |
Re: Problem mir StringResourcen...
Warum hältst du die maximale ID nicht auch als Resource vor?
marabu |
Re: Problem mir StringResourcen...
Dann könnt ich auch gleich hergehen und jedes mal die entspr. Schleife in meinem Programm anpassen....
Nein, ich will das nicht statisch lösen, sondern zur Laufzeit ermitteln :x ... Das es irgendwie gehen muß zeigen ja div. Resourcehacker, welche die Testresourcen auch exakt ermitteln können :gruebel: ... |
Re: Problem mir StringResourcen...
Die resource hacker analysieren die binären Daten der Resource. Übrigens, das mit deinen empty strings macht mich nachdenklich. Das WIN32 API kann nicht zwischen leeren oder fehlenden string resourcen unterscheiden - deshalb mein code weiter oben...
marabu PS: Auch wenn LoadString für leere und fehlende string resourcen die Länge 0 ermittelt - natürlich liefert GetLastError ERROR_RESOURCE_NAME_NOT_FOUND (1814) wenn nötig:
Delphi-Quellcode:
Aber du hast ja dein Problem gelöst...
// funktioniert nur bei fortlaufender ID
function GetMaxStringID(start: integer): integer; begin Result := start; repeat if (LoadStr(Result) = '') and (GetLastError = ERROR_RESOURCE_NAME_NOT_FOUND) then Break else Inc(Result); until false; if Result = start then Result := -1 else Result := Pred(Result); end; |
Re: Problem mir StringResourcen...
Zitat:
//EDIT: schon wieder kein roter Kasten :evil: |
Re: Problem mir StringResourcen...
Hallo Flocke,
Zitat:
Freundliche Grüße vom marabu |
Re: Problem mir StringResourcen...
Also Reshack "merkt" auch nicht, wenn eine leere Stringresource (163 und 165) da ist:
![]() Ich hab jetzt meine Funktion angepasst und nun läuft sie korrekt:
Delphi-Quellcode:
function GetMaxResID: integer;
function EnumResourceNamesProc(Module: HMODULE; ResType: PChar; ResID: Integer; lParam: TStringList): Integer; stdcall; function Fill(Wert: string): string; begin Result := Wert; while Length(Result) < 6 do Result := '0' + Result; end; var i: integer; Buffer: array[0..MAX_PATH] of Char; begin lParam.Add(Fill(IntToStr(ResId))); Result := 1; end; var Buffer: array[0..MAX_PATH] of Char; n, LastSection: integer; MyList: TStringList; begin LastSection := 0; MyList := TStringList.Create; MyList.Sorted := True; windows.EnumResourceNames(hinstance, RT_STRING, @EnumResourceNamesProc, Integer(MyList)); if (MyList.Count > 0) and (StrToIntDef(MyList[0], -1) = 1) then begin Result := 0; LastSection := 1; for n := 1 to MyList.Count - 1 do begin if StrToIntDef(MyList[n], -1) = StrToIntDef(MyList[n - 1], -1) + 1 then LastSection := StrToIntDef(MyList[n], -1) else break; end; for n := (LastSection - 1) * 16 to (LastSection) * 16 do if LoadString(hinstance, n, @Buffer, MAX_PATH) > 0 then Result := n; end else Result := 0; MyList.Free; end; |
Re: Problem mir StringResourcen...
Tcha, dann gibt es die entweder nicht, weil sie leer sind (und das Ergebnis bei LoadString bleibt sich ja sowieso gleich), oder man muß es direkt über die Strukturen der PE-Datei versuschen.
|
Re: Problem mir StringResourcen...
Zitat:
Der String, den man mit LoadString(N) lädt, steht in der Ressource vom Typ RT_STRING mit dem Namen MAKEINTRESOURCE((N div 16)+1) an Position (N mod 16). Wenn also der String 3 definiert ist, dann kann man rein technisch nicht mehr unterscheiden ob die Strings 0-2 und 4-15 auch definiert waren (eben leer) oder nicht. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:35 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-2025 by Thomas Breitkreuz