Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Resourcestring laden (https://www.delphipraxis.net/110254-resourcestring-laden.html)

Neutral General 15. Mär 2008 14:27


Resourcestring laden
 
Hi,

Generell ist das ja mit LoadString kein Problem, aber ich habe genau das gleiche Problem wie es hier beschrieben.

Delphi-Quellcode:
resourcestring
  hallo = 'Hallo DP!';
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.

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

turboPASCAL 15. Mär 2008 16:51

Re: Resourcestring laden
 
Delphi-Quellcode:
resourcestring
  hallo = 'Hallo DP!';

procedure Foo;
begin
  MessageBox(hWnd, PCHAR(hallo), '!', MB_OK);
end;
Das macht Delphi für dich. :wink:

Neutral General 15. Mär 2008 17:58

Re: Resourcestring laden
 
Problem ist aber das ich keinen Zugriff auf die "Resourcestring-Variable" habe.

Also quasi so:

Delphi-Quellcode:
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.
Gruß
Neutral General

omata 15. Mär 2008 18:01

Re: Resourcestring laden
 
Wie wäre es so...

Delphi-Quellcode:
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.
Gruss
Thorsten

sakura 15. Mär 2008 18:01

Re: Resourcestring laden
 
Zitat:

Zitat von Neutral General
Problem ist aber das ich keinen Zugriff auf die "Resourcestring-Variable" habe.

Da hast Du gar keine Chance. Da die Resource IDs der Strings vor dem kompilieren nicht fest vergeben werden und mit dem hinzufügen weiterer Strings (müssen nicht mal unbedingt Resourcestrings sein!) die ID sich immer wieder ändert, gibt es keinen Weg da ran zu kommen.

...:cat:...

Neutral General 15. Mär 2008 18:03

Re: Resourcestring laden
 
Hi,

@omata: Ne so kann ichs auch nicht machen. Wie gesagt - Ich kann/darf nicht tricksen...

@sakura: Das ist schlecht :?

turboPASCAL 15. Mär 2008 18:09

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:

Zitat von Neutral General
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.

Wieso, weshalb und warum frag ich mal ganz dumm ?

Neutral General 15. Mär 2008 18:31

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

omata 15. Mär 2008 18:36

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

turboPASCAL 15. Mär 2008 19:09

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.

Neutral General 15. Mär 2008 19:11

Re: Resourcestring laden
 
Zitat:

Zitat von omata
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

Hi,

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:

STRINGTABLE
{
0, "FormCreate" // Name der Create-Methode;
}
Ich dachte mir jetzt, das es um einiges komfortabler wäre wenn ich es so machen könnte:


Delphi-Quellcode:
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.
statt

Zitat:

STRINGTABLE
{
0, "FormCreate" // Name der Create-Methode;
}
erstellen, kompilieren und einbinden:

Delphi-Quellcode:
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.
Gruß
Neutral General

omata 15. Mär 2008 19:18

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

Neutral General 15. Mär 2008 19:26

Re: Resourcestring laden
 
Hi^^

Also

eine Unit:

Delphi-Quellcode:
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.
andere Unit:

Delphi-Quellcode:
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.
Und weil das wie gesagt mit ner .rc/.res Datei zu nervig ist wollte ichs so machen:

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:
unit NVCLForms;

//...

constructor TNVCLForm.Create(AParent: TNVCLControl);
var resStr: String;
begin
  // resourcestring laden
  -->???????<--
end;

// ...

end.
Gruß
Neutral General

omata 15. Mär 2008 19:39

Re: Resourcestring laden
 
Kannst du diesen String nicht im Konstruktor mit übergeben?

Neutral General 15. Mär 2008 19:40

Re: Resourcestring laden
 
Könnte ich, aber würde dir das gefallen als Benutzer?

omata 15. Mär 2008 19:43

Re: Resourcestring laden
 
Welchen Inhalt enthält der Ressourcenstring den? Wofür ist dieser genau da?

Die Muhkuh 15. Mär 2008 19:44

Re: Resourcestring laden
 
Zitat:

Zitat von omata
Welchen Inhalt enthält der Ressourcenstring den? Wofür ist dieser genau da?

Das versuche ich auch gerade zu verstehen.

omata 15. Mär 2008 20:10

Re: Resourcestring laden
 
Zitat:

Zitat von Die Muhkuh
Das versuche ich auch gerade zu verstehen.

Das beruhigt mich jetzt. Ich dachte schon ich bin hier der einzige der das nicht versteht.

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)

Neutral General 15. Mär 2008 20:11

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

Neutral General 16. Mär 2008 15:15

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:
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;
Bisher habe ich es ähnlich gelöst wie die VCL. In der Exe wird ein Resoucestring gespeichert
(per {$R a.res} ).

Hier der ganze Weg:

FormCreate.rc

Zitat:

STRINGTABLE
{
0, "FormCreate" // Name der Create-Methode;
}
:arrow: compilieren :arrow: FormCreate.res

Unit1:

Delphi-Quellcode:
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.
Project1

Delphi-Quellcode:
program Project1;

uses
  NVCLForms,
  Unit1 in 'Unit1.pas';

begin
  Application.CreateForm(Form1,TForm1); // Form1 wird erstellt...
  Application.Run;
end.
:arrow:

Delphi-Quellcode:
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

  // [...]
:arrow: Mein Fenster erhält WM_CREATE:

Delphi-Quellcode:
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;
:arrow:

Delphi-Quellcode:
unit Unit1;

// [...]

implementation

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Code wird ausgeführt!
end;

end.
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.

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:
resourcestring
  FormCreate = 'FormCreate';
Das Problem taucht dann aber hier auf:

Delphi-Quellcode:
SetLength(resStr,255);
LoadString(hInstance,Index,@resStr[1],255); // Index unbekannt von 'FormCreate'
MyTrim(resStr);
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).

Verstanden ? :?

Gruß
Neutral General

Apollonius 16. Mär 2008 15:40

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.

dominikkv 16. Mär 2008 15:52

Re: Resourcestring laden
 
oder kann man nicht Klassenmethoden nehmen?

omata 16. Mär 2008 17:03

Re: Resourcestring laden
 
Hier mal ein neuer Vorschlag...

Delphi-Quellcode:
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;
Aufruf...
Delphi-Quellcode:
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;
Bei dieser Vorgehensweise könnte man die Übergabe auch über den Konstruktor machen? oder nicht, weil dann das Application.CreateForm nicht geht?

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

Apollonius 16. Mär 2008 17:53

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:
FormVar := FormClass.NewInstance;
FormVar.Create;
gearbeitet wird, sonst ist die Variable noch nicht zugewiesen.

Neutral General 16. Mär 2008 18:09

Re: Resourcestring laden
 
Zitat:

Zitat von omata
Hier mal ein neuer Vorschlag...

[...]

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

Hab ich dir was getan, das bei jeder deiner Antworten mit sowas ankommst? Wieso gehst du davon aus das es mir nicht gefällt? Und glaubst du mir gefällt das irgendwie aus Prinzip nicht weils von dir ist oder was? Wenn mir was nicht gefällt, dann habe ich einen anständigen Grund dazu.

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:

Zitat von Apollonius
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:
FormVar := FormClass.NewInstance;
FormVar.Create;
gearbeitet wird, sonst ist die Variable noch nicht zugewiesen.

Ich werde mir deine Idee mal durchn Kopf gehn lassen ;)

omata 16. Mär 2008 19:35

Re: Resourcestring laden
 
Zitat:

Zitat von Neutral General
Hab ich dir was getan...

Nein, ich war nur etwas genervt. Ich wollte das mal mit einem konkreten Beispiel ausprobieren. Ich finde aber kein vollständiges, um es mal mit deinen Quellcode-Schnipseln testen zu können.
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

Neutral General 18. Mär 2008 12:56

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:
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;
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.

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