MultiLanguage-Support mit Satellite DLLs
-
Hallo @all,
ich bin gerade dabei ein Programm von mir für die Nutzung verschiedener Sprachen umzustellen.
Ich möchte das so umsetzen, dass ich die einzelnen Ressourcen in dedizierte Sprach-DLLs auslagere.Das funktioniert soweit auch recht gut, jetzt habe ich nur ein Problem. Wenn die Sprache innerhalb der Dialoganwendung "on-the-fly" umgestellt werden soll, ändern sich alle Dialoge die neu initialisiert werden.
Das Problem ist, dass der Hauptdialog nicht geupdatet wird. Gibt es eine Möglichkeit zu forcieren, dass auch im Hauptdialog die Ressourcen neu geladen werden?

Ein einfaches Invalidate() zum Neuzeichnen des Bildschirmbereichs bzw. AfxSetResourceHandle(hInst); reicht leider nicht aus, wie gesagt nur für die neu erzeugten Dialoge.
-
Genau diese Frage habe ich mir vor einigen Jahren auch gestellt.
Ich gehe davon aus, dass du für jede Sprache eine reine Resource-DLL (/NOENTRY) hast, die nach Umstellung auf eine andere Sprache geladen werden soll.Du kannst Deinen Dialog programmtechnisch erzeugen (also nicht über ein Dialog Template im Resource Editor), alle Texte aus dem Stringtable laden, und nach ändern der Sprache alle Controls nach dem Aufruf von AfxSetResourceHandle(hInst) über LoadString(..) neu beschreiben.
Das Problem liegt darin, dass das "Basistemplate" (bei MDI/SDI sind das z.B. Menüs, bei Dialogapplikationen halt der erste "Basisdialog") geladen wird, und bis zum Programmende gültig bleibt.
Daher, so habe ich es gelöst, eine freundliche Meldung an den Endanwender:
"Diese Änderungen erfordern einen Neustart des Programmes."
-
Oh nein Gio, genau auf diese Antwort habe ich NICHT gehofft.

Genau wie du es beschrieben hast habe ich die Ressourcen-DLLs erzeugt.
Aber ich habe irgendwie noch die Hoffnung, dass es trotzdem auch für eine Dialoganwendung funktionieren müsste.
Wenn man eine Menüanwendung hat, gibt es die Möglichkeit ein Handle auf das Menü zu holen, das Menü zu zerstören und dann neu aus der Ressource einzulesen und die View upzudaten.Kann man nicht auf irgendeine Weise den 1. Dialog zerstören und sofort wieder neu einlesen?

-
Wie das sauber geht, weiss ich leider auch nicht...
Ich würde aber versuchen den Hauptdialog zu schliessen mittels EndModalLoop()
und dann wieder anzeigen.Wie gesagt nur eine Vermutung..........
-
Dressman1981 schrieb:
Wenn man eine Menüanwendung hat, gibt es die Möglichkeit ein Handle auf das Menü zu holen, das Menü zu zerstören und dann neu aus der Ressource einzulesen und die View upzudaten.
Aber selbst das ist unvollständig. Man muss die Doc-Templates alle neu aufbauen, ohne die alten Daten zu verändern.
Intern in der MFC gibt es einigen Code der nicht so einfach neu geladen werden kann.Dressman1981 schrieb:
Kann man nicht auf irgendeine Weise den 1. Dialog zerstören und sofort wieder neu einlesen?

Es kann dazu keine Technik geben, denn aus den Ressourcen wird einfach in einer Schleife CreateWindow durchgeführt. Und wenn ActiveX Controls im Spiel ist macht die MFC noch ganz andere verrückte Sachen.
Wenn Dein Dialog gut konzipiert ist, dann werden alle Daten mit DoDataExchange geladen und gespeichert. Also einfach EndDialog(IDC_LANGCHANGE); (o.ä.) durchführen und den Dialog neu starten.
Aber wichtig! Vorher das m_pMainWnd auf NULL setzen und nach dem erneuten Start wieder setzen. Sonst wird WM_QUIT versendet!
PS: Die Diskussion um eine direkte Sprachumschaltung ist alt. Nur finde ich sie absolut überflüssig. Ein User startet ein Programm und wählt seine Sprache. Das macht er wahrscheinlich genau einmal nach der Installation! Danach wird er die Sprache behalten. Warum darf man ihn für diesen einen Fall nicht zu einem Neustart bitten?
Just my 2 cents
-
Martin Richter schrieb:
Warum darf man ihn für diesen einen Fall nicht zu einem Neustart bitten?
Just my 2 centsWenn ich MFC verwende mache ich es auch genauso (also mit Neustart). Allerdings lade ich meine Strings dann trotzdem lieber aus einem .ini File - aber das ist Geschmackssache.
Gegenfrage: wieso verwendet man nicht einfach eine Library die problemlos on-the-fly Sprachen umschalten ermöglicht?
-
Hallo und danke für alle Antworten und Tipps!
@hustbaer:
Die Idee mit den ini-Dateien ist mir auch zunächst gekommen.
Teilweise kann es aber erforderlich sein einen Dialog bzw. die Bilder etc. sprachspezifisch anzupassen, da ist der Weg über die RessourcenDLLs sinnvoller.Wie würdest du denn vorgehen, um solch eine Library zu erstellen, die in der Lage ist die Sprachen on-the-fly umzustellen?

-
Dressman1981 schrieb:
Wie würdest du denn vorgehen, um solch eine Library zu erstellen, die in der Lage ist die Sprachen on-the-fly umzustellen?

On the fly ist immer ein Problem, denn es gibt einfach Speicher der allokiert wurde, Stringvariablen, die irgendwo im Speichermanagament rumliegen und schon hat man beim umstellen ein Problem.
Ich finde es viel lästiger, dass es mühsamst ist, auch Message-Boxen und Standdard-Dialogein der entsprechenden Sprache anzuzeigen.
Du bist immer noch eine Erklärung schuldig warum On-The-Fly soooo wichtig ist. Siehemeine Frage und Erklärung in einem früheren Posting.
-
Dressman1981 schrieb:
Wie würdest du denn vorgehen, um solch eine Library zu erstellen, die in der Lage ist die Sprachen on-the-fly umzustellen?

Ich würde so eine Library nicht erstellen, sondern erstmal gucken ob's nicht schon was fertiges gibt was das kann. Sollte es für C++ wirklich nixe geben, dann würde ich auf jeden Fall die Dialoge programmatisch aufbauen, und nicht aus Templates. Dabei kommen dann diverse Hilfklassen zum Einsatz die z.B. Elemente übereinander/nebeneinander anordnen etc. - so wie man das halt auch aus Java kennt.
Jedes Element hat dabei ein paar Standardeigenschaften, z.B. minimale und maximale Breite/Höhe. Wenn sich der Text eines Buttons z.B. ändert, dann ändert sich automatisch auch dessen minimale Breite. Die Layout Hilfsklassen müssen dann dafür sorgen dass diese min/max Werte (wenn möglich - das Fenster kann ja nicht unendlich gross werden) eingehalten werden.
Beim anlegen eines Buttons z.B. gibst du dem dann nicht den Text mit den er anzeigen soll, sondern die Text ID. Die Library weiss dann welche Sprache gerade eingestellt ist, und lädt den String von wo-auch-immer.
Wenn man dann die Sprache umschalten will muss man bloss alle Elemente des Dialoges durchgehen, die Strings neu laden, und dann die Layout-Hilfsklassen neu arbeiten lassen.
Strings die man im Programm selbst angreifen muss holt man sich dabei am besten immer vom "String-Loader" - der kann ja Strings auch ohne weiteres cachen - dann bremst das auch nicht schlimm.
----
Da sowas selbst zu entwickeln aber viel viel Arbeit ist würde ich wie gesagt gucken ob es nicht bereits eine Library für Windows gibt die das kann.
-
@Martin Richter:
Es gibt keine Vorgabe oder Ähnliches, warum ich die Sprache direkt im Programmablauf umstellen möchte. Ich will mich trotz alledem informieren, ob soetwas möglich ist und wenn ja wie, da ich es persönlich angenehmer und irgendwie auch professioneller finden würde.@hustbaer:
Danke noch mal für dein ausführliches Posting.
Ich habe bereits vor dem Eröffnen meiner Frage auf den gängigen Seiten geschaut (www.codeproject.com bzw. www.codeguru.com) und da nur allgemeine Vorschläge bezüglich der RessourcenDLL's gefunden.Auf jeden Fall hört sich deine Beschreibung recht gut an. Ich werde mal noch weiter suchen und wenn ich soetwas nicht finden sollte wohl selbst in Angriff nehmen.
@all: Falls jemanden durch Zufall mal solch eine Klasse beim Durchstöbern des Netzes auffallen sollte, wäre es super, wenn das jemand hier posten könnte.