From: Joseph M. Newcomer on
See below...
On Sat, 19 Jun 2010 19:59:56 +0100, "David Webber" <dave(a)musical-dot-demon-dot-co.uk>
wrote:

>"mfc" <mfcprog(a)googlemail.com> wrote in message
>news:b9035371-3a58-4c69-85f4-da5ba2210472(a)h13g2000yqm.googlegroups.com...
>
>> I`ve a sdi application where I want to add multiple language support.
>> If the user press the button btn1, the language should be changed.
>>...
>
>Vis a vis some of Joe's criticisms, the way I do it is as follows:
>
>Resource only DLLs are in the same directory as the exe. They all have
>names of the form
>
>mozartfra.dll
>mozartdeu.dll
>mozartcym.dll
>
>At launch the program looks for all dlls with names of this form
>(mozart???.dll) , and attempts to load one or two strings from their
>resources, including the full name of the language
>
> (francais)
> (deutsch)
> (cymraeg)
***
I didn't bother to load the DLLs explicitly, I used a field in the VERSIONINFO to hold the
printable string I wanted: "Keyboard", "Fretted Instrument", "Score" and just used that to
find my menu string
****
>
>which is (by my defined convention) always present with the same resource
>ID.
>
>From this I construct a table of language-name vs dll-name (the letters in
>the dll name are just for my convenience - the program doesn't need them).
>Then it unloads all the DLLs.
****
I did the same trick
****
>
>When you need to change language, the program presents a list of language
>names, and selecting the language loads the corresponding DLL, and remembers
>its HINSTANCE.
>
>All resources are loaded from within members of a language manager class,
>which holds the HINSTANCE of the language DLL in use (or NULL if English)
>and the hInstance of the main program (with the English resources).
>
>The language manager class constructor, remembers the current resource
>handle and calls AfxSetResourceHandle() to the DLL where the resources are
>required. The destructor sets AfxSetResurceHandle() to the old HINSTANCE.
>All calls to loading strings, menus, dialogues, toolbars,.... are done from
>members of the language manager class, so they must be done between
>construction and destruction, when the resource handle is as desired.
>
>It works quite transparently, and no-one knows what language any DLL
>contains except the DLL itself!
>
>Dave
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Mihai N. on
> I`ve a sdi application where I want to add multiple language support.
> If the user press the button btn1, the language should be changed.

For anything beyond a trivial application, you should just give up.
Once you change the current resource dll, to update everything you
would really have to destroy all existing menus and dialogs and
re-load them from the new dll, refresh all views, update all titles,
etc.

The use cases where an "on they fly" update is justified are realy low.

I would recomend to do what most applications do: once the user changes
the language, save the setting somewhere, show a message saying
"the change will take effect the next time you start the application"
and call it a day.
At the next application start read the saved setting very-very early
in the startup process and load the resource dll.


--
Mihai Nita [Microsoft MVP, Visual C++]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email

From: mfc on
>Note also that features that *require* correct settings in the Registry are *very*
>suspect. You *must* assume that *no* Registry key or value is defined, and do something
>intelligent anyway. Defaulting to the default user locale is a good approach. I refuse
>to use SetRegistryKey because of all the problems it has.
joe

Which way do you prefer in the initInstance method instead of using
SetRegistryKey?

InitCommonControls();
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
m_LanguageSupport.LoadBestLanguage(); // <-- Add this line (after the
call to SetRegistryKey)
LoadStdProfileSettings(4);

best regards
Hans

And many thanks for your time to help me get this prog working
From: David Webber on


"Mihai N." <nmihai_year_2000(a)yahoo.com> wrote in message
news:Xns9D9D15F01DF9DMihaiN(a)207.46.248.16...
>> I`ve a sdi application where I want to add multiple language support.
>> If the user press the button btn1, the language should be changed.
>
> For anything beyond a trivial application, you should just give up.
> Once you change the current resource dll, to update everything you
> would really have to destroy all existing menus and dialogs and
> re-load them from the new dll, refresh all views, update all titles,
> etc.
>
> The use cases where an "on they fly" update is justified are realy low.
>
> I would recomend to do what most applications do: once the user changes
> the language, save the setting somewhere, show a message saying
> "the change will take effect the next time you start the application"
> and call it a day.
> At the next application start read the saved setting very-very early
> in the startup process and load the resource dll.

With the *old* menu structure generated by the AppWizard, it isn't hard to
do it on the fly. Just load the new menu from the DLL for Document present
(hMenuDoc) and no Document present, (hMenuNoDoc) and then:

// Update the document menu, which is held as a static member
// of CMyDoc:

HMENU hMenuDocOld = CMyDoc::mdDefaultMenuSet( hMenuDoc );

// Update the non-document menu, which is held as
// m_hMenuDefault in the frame window:

HMENU hMenuNoDocOld = pFrameWnd->m_hMenuDefault; // the current
default.
pFrameWnd->m_hMenuDefault = hMenuNoDoc;
pFrameWnd->OnUpdateFrameMenu( NULL );
pFrameWnd->DrawMenuBar();

// Tidy up old menus:

if( hMenuDocOld ) ::DestroyMenu( hMenuDocOld );
if( hMenuNoDocOld ) ::DestroyMenu( hMenuNoDocOld );

with:

HMENU CMyDoc::mdDefaultMenuSet( HMENU hMenuDoc )
{
HMENU hMenuOld = m_hMenuMzDocument;
m_hMenuMzDocument = hMenuDoc;
return hMenuOld;
}

Caveat: I have yet to find out whether this works with fancy new
CMFCMenuBar, but I intend to explore it before too long.

Dave
--
David Webber
Mozart Music Software
http://www.mozart.co.uk
For discussion and support see
http://www.mozart.co.uk/mozartists/mailinglist.htm

From: Goran on
On Jun 19, 4:15 pm, Joseph M. Newcomer <newco...(a)flounder.com> wrote:
> Why is code to manipulate TheApp not part of the CWinApp-derived class?
>
> If this code is manipulating the CWinApp-derived class, this handler should be part of the
> CWinApp-derived class, not the main frame!
>
> Oh, I see.  To avoid a "global variable", you tossed some random stuff into the CWinApp
> class.  As a style, this sucks.

Yes, yes, yes.

To expand: doing this as a matter of fact, over time, creates MASSIVE
compile-time dependencies. I have that (decade,5 old code base). I
can't tell how much I've come to despise them. I really wish MSDN said
something on the lines of "never add, only override, members of
CWinApp" from the get go (when I was learning it). In fact, I remember
tutorials saying quite the opposite. :-(

I also wish tutorials said: "apply interface segregation principle to
your document class", for same compile-time dependencies reason. But I
can't blame MFC people for that; I don't think ISP was even formulated
when MFC was coming out :-(.

Goran.
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9
Prev: I love MFC!
Next: Using CMFCToolBar and CMFCMenuBar?