Einzelnen Beitrag anzeigen

Benutzerbild von TheMiller
TheMiller

Registriert seit: 19. Mai 2003
Ort: Gründau
2.480 Beiträge
 
Delphi XE7 Architect
 
#1

Multilingual mit DLLs u. Unicode - so richtig?

  Alt 31. Aug 2011, 20:35
Hallo,

ich habe jetzt ein System für Mehrsprachenunterstützung fertig, welches auch für Unicode geeignet sein sollte. Ich würde gerne wissen, ob das alles so richtig/in Ordnung ist. Ich weiß, dass es gnugetext etc gibt, ich mag aber nicht noch mehr Abhängigkeiten im Programm haben.

Anmerkungen: Ist angelehnt an Luckies Artikel StringDLLs und an Unicode angepasst (bzw. sollte so sein). Auch habe ich beide Projekte mit FastMM auf Leaks getestet.

Hinweis:
- Beide Projekte haben eine LanguageID-Unit eingebunden, die die Konstanten entählt.

Hier mal der komplette Quelltext:

Von der DLL
Delphi-Quellcode:
library de;

uses
  SysUtils,
  LanguageIDs;

{$R *.res}

function getText(str: Integer): PWideChar;
begin
  case str of
    BUTTON1_C:
      result:='Einloggen';
    BUTTON1_H:
      result:='Hier klicken, um einzuloggen';
  end;
end;

function getCompName(str: PWideChar): PWideChar;
begin
  if (str = 'Button1') then
    result:='Bitte hier nicht drücken';
end;

//Ersetzt später Captions und Hints nach Komponentenname
function _compName(comp: PWideChar; Buffer: PChar; lenBuffer: Integer): Integer; stdcall;
begin
  if Assigned(Buffer) then
    StrLCopy(Buffer, PWideChar(getCompName(comp)), lenBuffer);
  result := length(getCompName(comp));
end;

//Ruft einfach nur Text ab.
function _lang(str: Integer; Buffer: PWideChar; lenBuffer: Integer): Integer; stdcall;
begin
  if Assigned(Buffer) then
    StrLCopy(Buffer, PWideChar(getText(str)), lenBuffer);
  result := length(getText(str));
end;

exports
  _lang,
  _compName;

begin
end.
Haupt-Programm
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Edit1: TEdit;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    function _l(strName: Integer): String;
    function _cl(compName: String): String;
  end;

  TLang = function (str: Integer; Buffer: PChar; lenBuffer: Integer): Integer; stdcall;
  TComp = function (comp: PChar; Buffer: PChar; lenBuffer: Integer): Integer; stdcall;

var
  Form1: TForm1;
  hLib: THandle;
  s: String;
  Lang: TLang;
  Comp: TComp;
  len: Integer;
  Buffer: PChar;

implementation

{$R *.dfm}

{****** Holt den Text aus der DLL **********}
function TForm1._l(strName: Integer): String;
begin
  len:=lang(strName, nil, 0);
  try
    // Hier Unicode-Anpassung: jeweils 2 Byte pro Char + 2 Bytes für Stopp: \0
    GetMem(Buffer, len*2+2);

    // Hier Unicode-Anpassung: jeweils 2 Byte pro Char + 2 Bytes für Stopp: \0
    len:=lang(strName, Buffer, len*2+2);

    result:=String(Buffer);
  finally
    FreeMem(Buffer);
  end;
end;


{****** Holt einen Componentennamen aus der DLL **********}
function TForm1._cl(compName: string): String;
var
  s: String;
begin
  len:=comp(PWideChar(compName), nil, 0);
  try
    // Hier Unicode-Anpassung: jeweils 2 Byte pro Char + 2 Bytes für Stopp: \0
    GetMem(Buffer, len*2+2);

    // Hier Unicode-Anpassung: jeweils 2 Byte pro Char + 2 Bytes für Stopp: \0
    len:=comp(PWideChar(compName), Buffer, len*2+2);

    result:=String(Buffer);
  finally
    // Speicher wieder freigeben
    FreeMem(Buffer);
  end;
end;


procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  hLib := LoadLibrary('de.dll');

  // Beim Laden ist ein Fehler aufgetreten
  if hLib = 0 then
  begin
    Str(GetLastError, s);
    ShowMessage(SysErrorMessage(GetLastError));
    exit;
  end;

  //Funktion laden
  @lang := GetProcAddress(hLib, '_lang');

  //Beim Laden der Funktion ist ein Fehler aufgetreten.
  if (not Assigned(lang)) then
  begin
    Str(GetLastError, s);
    ShowMessage(SysErrorMessage(GetLastError));
    exit;
  end;

  //Funktion laden
  @comp := GetProcAddress(hLib, '_compName');

  //Beim Laden der Funktion ist ein Fehler aufgetreten.
  if (not Assigned(comp)) then
  begin
    Str(GetLastError, s);
    ShowMessage(SysErrorMessage(GetLastError));
    exit;
  end;

  //Spezielle Komponententexte ersetzen.
  for i:=0 to Form1.ComponentCount-1 do
  begin
    if (Form1.Components[i].ClassName = 'TButton') then
    begin
      (Form1.Components[i] as TButton).Caption:=_cl(Form1.Components[i].Name);
    end;
  end;

  FreeLibrary(hlib);
end;

end.
Also. Fehler treten keine auf und es funktioniert eigentlich alles wunderbar. Die Frage ist nur, ob das wirklich so richtig ist. Würde das gerne vorher wissen, bevor ich weitermache. Vielleicht hilft dieser Beitrag ja dem Einen oder Anderen.

Danke im Voraus
  Mit Zitat antworten Zitat