Resourcestring laden
Hi,
Generell ist das ja mit LoadString kein Problem, aber ich habe genau das gleiche Problem wie es hier beschrieben.
Delphi-Quellcode:
Diesen String will ich jetzt laden. EDatabaseError wurde geraten Stringtables zu benutzen. Das geht aber bei mir nicht. Also es geht schon aber ich will/kann sie nicht benutzen.
resourcestring
hallo = 'Hallo DP!'; Das heißt: Ziel dieses Threads ist wirklich herauszufinden wie man solche Strings laden kann. Das muss ja irgendwie möglich sein... Gruß Neutral General |
Re: Resourcestring laden
Delphi-Quellcode:
Das macht Delphi für dich. :wink:
resourcestring
hallo = 'Hallo DP!'; procedure Foo; begin MessageBox(hWnd, PCHAR(hallo), '!', MB_OK); end; |
Re: Resourcestring laden
Problem ist aber das ich keinen Zugriff auf die "Resourcestring-Variable" habe.
Also quasi so:
Delphi-Quellcode:
Gruß
unit Unit1;
interface uses Dings; resourcestring Dings = 'Lala ein String'; end. { ------------------------------------------------------------------------ } unit Dings; uses Alles; nurNicht_Unit1; // Muss trotzdem an den Inhalt von "Dings" drankommen! end. Neutral General |
Re: Resourcestring laden
Wie wäre es so...
Delphi-Quellcode:
Gruss
unit RessourceU;
interface resourcestring Dings = 'Lala ein String'; implementation end. unit Unit1; interface uses DingsU, RessourceU; implementation end. unit DingsU; uses Alles, RessourceU, nurNicht_Unit1; // Muss trotzdem an den Inhalt von "Dings" drankommen! end. Thorsten |
Re: Resourcestring laden
Zitat:
...:cat:... |
Re: Resourcestring laden
Hi,
@omata: Ne so kann ichs auch nicht machen. Wie gesagt - Ich kann/darf nicht tricksen... @sakura: Das ist schlecht :? |
Re: Resourcestring laden
Was omata beschreibt hat nichts mit Tricksen zu schaffen. Es ist lediglich eine Unit die halt
in deinem Fall die Stringresourcen enthält. Zitat:
|
Re: Resourcestring laden
Hi turboPASCAL
Naja wie du vielleicht weißt, arbeite ich an einer eigenen VCL.. Und für das OnCreate der Form muss ein Resourcestring in die Exe gepackt werden (wird bei der normalen VCL im Prinzip genauso geregelt, in Form der dfm). Leider ist es etwas nervig manuel eine .res Datei in sein Projekt einzubinden und diese vorher zu erstellen. Viel leichter wäre es wenn man in den Source einfach einen Res-String schreiben könnte und fertig. Also ums mal deutlich zu machen: Du würdest Borland/Codegear auch was erzählen wenn du die dfm-Datei selbst schreiben müsstest oder?^^ Gruß Neutral General |
Re: Resourcestring laden
Also du möchtest auf einen Ressourcenstring zugreifen, der in der selben Unit deklariert ist -> ok.
Aber was soll dann bitte der Zugriff in einer Unit, die nichts von der anderen Unit weiss, in der der Ressourcenstring deklariert ist? Sorry, aber ist irgendwie nicht durchdacht. Gruss Thorsten |
Re: Resourcestring laden
Die *.Dfm - Datei ist eine "Eigenentwicklung" von Borland. Die packen das dann als
RT_RCDATA in den Resourcebereich der Datei. Die Infos der Datei lesen sie dann mit einer eigenen Procedure aus. So kannst du das ja ggf. auch machen. |
Re: Resourcestring laden
Zitat:
Also pass auf: 1. Kann man ResourceStrings generell mit LoadString laden ohne das die Strings irgendwie irgendwo inner Unit verankert sind, also nichts soo außergewöhnliches 2. Stell dir vor du bindest meine NonVCL Units in dein Programm ein. So und jetzt willst du natürlich das auch das OnCreate der Form funktioniert. Dann hast du bisher nur die möglichkeit dir ne .rc Datei zu schreiben, diese zu compilieren und ins Projekt einzufügen. Das ist natürlich ätzend und nervig. In dieser Resourcedatei würde dann z.B. drinstehn Zitat:
Delphi-Quellcode:
statt
unit Unit1;
interface uses NVCLForms; type TForm1 = class(TNVCLForm) procedure FormCreate(Sender: TObject); private public end; resourcestring TForm1OnCreate = 'FormCreate'; implementation { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin // Code end; end. Zitat:
Delphi-Quellcode:
Gruß
unit Unit1;
interface uses NVCLForms; type TForm1 = class(TNVCLForm) procedure FormCreate(Sender: TObject); private public end; {$R FormCreate.res} implementation { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin // Code end; end. Neutral General |
Re: Resourcestring laden
Ja, das ist ja alles sehr schön.
Nur was soll mir das jetzt sagen? In deinem ersten Beispiel ging es um eine zweite Unit, jetzt hast du nur noch eine. Naja, du wirst das schon hinbekommen. Ich bin vermutlich einfach zu blöd, um das zu verstehen. Gruss Thorsten |
Re: Resourcestring laden
Hi^^
Also eine Unit:
Delphi-Quellcode:
andere Unit:
unit Unit1;
interface uses NVCLForms; type TForm1 = class(TNVCLForm) procedure FormCreate(Sender: TObject); private public end; {$R FormCreate.res} implementation { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin // Code end; end.
Delphi-Quellcode:
Und weil das wie gesagt mit ner .rc/.res Datei zu nervig ist wollte ichs so machen:
unit NVCLForms;
//... constructor TNVCLForm.Create(AParent: TNVCLControl); var resStr: String; begin // resourcestring laden // bisher so: SetLength(resStr,High(Byte)); LoadString(hInstance,0,@resStr[1],255); // String wird geladen, geht aber nur mit .res datei Trim(resStr); end; // ... end.
Delphi-Quellcode:
unit Unit1;
interface uses NVCLForms; type TForm1 = class(TNVCLForm) procedure FormCreate(Sender: TObject); private public end; resourcestring FormCreate = 'FormCreate'; implementation { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin // Code end; end.
Delphi-Quellcode:
Gruß
unit NVCLForms;
//... constructor TNVCLForm.Create(AParent: TNVCLControl); var resStr: String; begin // resourcestring laden -->???????<-- end; // ... end. Neutral General |
Re: Resourcestring laden
Kannst du diesen String nicht im Konstruktor mit übergeben?
|
Re: Resourcestring laden
Könnte ich, aber würde dir das gefallen als Benutzer?
|
Re: Resourcestring laden
Welchen Inhalt enthält der Ressourcenstring den? Wofür ist dieser genau da?
|
Re: Resourcestring laden
Zitat:
|
Re: Resourcestring laden
Zitat:
Leider gibt es ja keine Antwort mehr von Neutral General, der ja die ganze Zeit online ist. Wir sind vermutlich nicht die richtigen Gesprächteilnehmer oder das Problem ist nicht oder nur mit sehr viel Aufwand zu erklären. Wie auch immer keine Antwort ist auch eine. (zumindest für mich) |
Re: Resourcestring laden
Sorry, es wird ne Antwort geben, keine Angst ;)
Die Muhkuh ist es gerade persönlich am testen und versucht mich zu verstehn^^ werde mich aber spätestens morgen mittag nochmal hier melden, entweder mit Lösung oder einer ausführlichen Erklärung ;) Gruß Neutral General |
Re: Resourcestring laden
Alsooo..
Ich will meiner TNVCLForm Klasse ein OnCreate Ereignis verpassen. Das habe ich sogar schon und es funktioniert. Das OnCreate kann man aber nicht so setzen wie ein "normales" Ereignis weil: :arrow: Man kann Ereignisse nur zuweisen, wenn die Klasse bereits erstellt ist :arrow: :arrow: Dann ist es aber für OnCreate zu spät. Soweit klar? Beispiel:
Delphi-Quellcode:
Bisher habe ich es ähnlich gelöst wie die VCL. In der Exe wird ein Resoucestring gespeichert
var form: TNVCLForm;
begin // 1. zu früh, wahrscheinlich AV form.OnCreate := FormCreate; form := TNVCLForm.Create; // 2. zu spät form := TNVCLForm.Create; form.OnCreate := FormCreate; end; (per {$R a.res} ). Hier der ganze Weg: FormCreate.rc Zitat:
Unit1:
Delphi-Quellcode:
Project1
unit Unit1;
interface uses NVCLForms; type TForm1 = class(TNVCLForm) procedure FormCreate(Sender: TObject); // Name der Methode = 'FormCreate' ! end; {$R FromCreate.res} // <-- FormCreate.res mit 'FormCreate'-String einbinden var Form1: TForm1; implementation { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin // Dieser Code soll ausgeführt werden end; end.
Delphi-Quellcode:
:arrow:
program Project1;
uses NVCLForms, Unit1 in 'Unit1.pas'; begin Application.CreateForm(Form1,TForm1); // Form1 wird erstellt... Application.Run; end.
Delphi-Quellcode:
:arrow: Mein Fenster erhält WM_CREATE:
constructor TNVCLForm.Create(AParent: TNVCLControl);
var resStr: String; _Create: TMethod; begin SetLength(resStr,255); // String wird aus der Exe geladen LoadString(hInstance,Index,@resStr[1],255); // ... Trim(resStr); // ... => 'FormCreate' _Create.Code := MethodAddress(resStr); // Addresse von TForm1.FormCreate herausfinden _Create.Data := Self; // ... FOnCreate := TCreateEvent(_Create); // FOnCreate := TForm1.FormCreate // [...]
Delphi-Quellcode:
:arrow:
procedure TNVCLForm.WndProc(var Message: TMessage);
begin case Message.Msg of WM_CREATE: begin if Assigned(FOnCreate) then FOnCreate(Self); // OnCreate wird ausgeführt end; // [...] end;
Delphi-Quellcode:
Ich hoffe das war jetzt nachvollziehbar. Der Nachteil dieser Methode ist, dass man immer erst eine .res Datei mit dem Namen der gewünschten OnCreate Methode zu erstellen, was ziemlich lästig ist.
unit Unit1;
// [...] implementation { TForm1 } procedure TForm1.FormCreate(Sender: TObject); begin // Code wird ausgeführt! end; end. Also dachte ich mir, wäre es für den Benutzer komfortabler wenn er nicht eine .res Datei erstellen müsste sondern nur irgendwo in sein Projekt
Delphi-Quellcode:
Das Problem taucht dann aber hier auf:
resourcestring
FormCreate = 'FormCreate';
Delphi-Quellcode:
Nun war meine Frage, wie man diesen String da gezielt laden kann (oder ob jemand notfalls noch eine andere Lösung für das Problem hätte).
SetLength(resStr,255);
LoadString(hInstance,Index,@resStr[1],255); // Index unbekannt von 'FormCreate' MyTrim(resStr); Verstanden ? :? Gruß Neutral General |
Re: Resourcestring laden
Ich finde diese Lösung mit den Strings zu kompliziert. Ich würde entweder eine virtuelle Methode nehmen, die beim Erstellen aufgerufen wird, oder alle als published deklarierten Methoden durchgehen, die in der Form-Klasse definiert werden, und nach 'Create' oder Ähnlichem suchen.
|
Re: Resourcestring laden
oder kann man nicht Klassenmethoden nehmen?
|
Re: Resourcestring laden
Hier mal ein neuer Vorschlag...
Delphi-Quellcode:
Aufruf...
type
TMyCustomForm = class(TForm) private FOnCreate:TNotifyEvent; public class procedure addOnCreate(EventName:string); constructor create(AParent: TControl); reintroduce; end; implementation var FOnCreateEventName:string; { TMyForm } class procedure TMyCustomForm.addOnCreate(EventName: string); begin FOnCreateEventName := EventName; end; constructor TMyCustomForm.create(AParent: TControl); var _Create: TMethod; begin _Create.Code := MethodAddress(FOnCreateEventName); _Create.Data := Self; if assigned(_Create.Code) then FOnCreate := TNotifyEvent(_Create) else FOnCreate := nil; if assigned(FOnCreate) then FOnCreate(Self); end;
Delphi-Quellcode:
Bei dieser Vorgehensweise könnte man die Übergabe auch über den Konstruktor machen? oder nicht, weil dann das Application.CreateForm nicht geht?
type
TMyForm = class(TMyCustomForm) published procedure FormCreate(Sender: TObject); end; : begin MyForm.addOnCreate('FormCreate'); MyForm:=TMyForm.create(Self); end; procedure TMyForm.FormCreate(Sender: TObject); begin end; Ich wollte dir eigentlich konkreter helfen, mit deinem Quellcode. Aber ich finde hier leider nirgends mal einen zusammenhängenden Quellcode von dir und dein Demo ist nur eine EXE. Vermutlich bin ich einfach nur blind. Naja, egal. Ich vermute mal das dir das sowieso wieder nicht gefällt. Wir drehen uns hier sowieso im Kreis. Du willst das nicht übergeben aber irgendwo must du das definieren. Ob nun in einer externen Datei oder direkt beim initialisieren. Gruss Thorsten |
Re: Resourcestring laden
Mir kommt gerade noch eine andere Idee: Eine Funktion schreiben, die für Form-Variablen Create-Handler registriert. Im Konstruktor wird dann geprüft, ob das Self das gleiche ist, was in einer der registrierten Variablen steht, wenn ja, dann wird der Handler aufgerufen. Das setzt aber voraus, das immer schön mit
Delphi-Quellcode:
gearbeitet wird, sonst ist die Variable noch nicht zugewiesen.
FormVar := FormClass.NewInstance;
FormVar.Create; |
Re: Resourcestring laden
Zitat:
Also zu deinem Vorschlag: Bei deinem ursprünglichen Vorschlag ist das Problem, das ich ein Problem bekomme, wenn es mehr als nur eine TNVCLForm-Klasse gibt (Mit unterschiedlich benannten OnCreate Methoden). Die Idee mit dem Konstruktor hatte ich auch schon aber, tut mir Leid, auch die gefällt mir irgendwie nicht so ganz :mrgreen: Abgesehn davon das die Forms ja durch Application.CreateForm erstellt werden und Application.CreateForm ruft ja erst den Konstruktor der Form auf. Von daher kann der "Benutzer" da auch nicht viel steuern, außer man übergibt dem Application.CreateForm diesen String. Aber mhh.. ich weiß nicht. Ich finde das irgendwie unschön. Also ich wills nochmal betonen. Ich lehne hier keine Vorschläge aus Prinzip ab! Die bisherigen sind meiner Meinung nach einfach zu unbefriedigend. :stupid: Gruß Neutral General EDIT: Da kam kein roter kasten -.- Zitat:
|
Re: Resourcestring laden
Zitat:
Wenn ich mir dann mal andere nonVCL-Beispiele ansehe, kann ich das nicht mit deinem Quellcode vereinbaren. Du benutzt immer noch TApplication? Dafür benötigst du dann die Unit Forms diese enthält dann die Units SysUtils, Classes. Ich dachte auf diese könnte man dann verzichten und erhält somit eine kleinere EXE? Wo liegt denn jetzt genau der Unterschied zwischen der VCL- und deiner nonVCL-Geschichte? Ich frage deshalb, weil ich sonst den Vorschlag hätte das Application-Objekt abzuleiten und um eine eigene CreateForm-Methode zu erweitern. Aber wenn du doch alles vom Delphieditor automatisch erstellen lassen möchtest, dann geht das natürlich nicht. Das verwirrt mich bzw. verstehe ich einfach immer noch nicht, sorry. Gruss Thorsten |
Re: Resourcestring laden
Hi,
Also omata: Application ist eine eigene Klasse ;) Ich binde natürlich nicht die VCL-Unit Forms ein, das würde mein Projekt ja total in totale Sinnlosigkeit stürzen^^ Also ich habe die Sache jetzt gelöst. Im TNVCLForm constructor:
Delphi-Quellcode:
Hab mir ne eigene RTTI Unit gebaut und damit + {$MethodInfo ON} funktioniert es. Also es wird die erstbeste Methode der Klasse genommen, die ein TCreateEvent ist.
begin
Methods := GetMethods(ClassType); // Alle Methoden auflisten n := -1; for i:= 0 to High(Methods) do if (Methods[i].ParamCount = 1) and (Methods[i].Params[0].Typ = 'TNVCLForm') then begin // Wenn eine Methode nur ein Parameter hat und der vom Typ TNVCLForm ist // Sprich: die Methode ein TCreateEvent ist, _Create.Code := MethodAddress(Methods[i].Name); _Create.Data := Self; FOnCreate := TCreateEvent(_Create); //... dann wird sie dem OnCreate zugewiesen break; end; Ich werde in absehbarer Zeit eine Alpha-Version meiner VCL hochladen, und dann könnt ihr sie selbst mal ausprobieren. Dann wird das ganze vielleicht (wenn auch im Nachhinein^^) klarer ;) Gruß Neutral General |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:59 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