Bill Roper (billroper) wrote,
Bill Roper

Reloading MFC Language Resources

MFC does not have wonderful support for changing languages on the fly in a running application by reloading the underlying resource DLL. It turns out that this is something you can do -- you just have to get your incantations straight.

There are two places where loaded menus should reside in an MFC application -- in the CFrameWnd that represents the application's mainframe window and in any CMultiDocTemplate classes that belong to the app, assuming that you're running an MDI application. When you reload the resources, you need to unload and replace the menu and accelerator resources for the mainframe and for each of the CMultiDocTemplates.

That's fairly easy to do. The CWinApp owns the templates (via the CDocManager class), so it should be responsible for unloading the menus there:

void CMyDocTemplate::ReloadTemplate()
// Destroy the resources from CDocTemplate

// Delete OLE resources from CDocTemplate
if (m_hMenuInPlace != NULL) {
m_hMenuInPlace = NULL;

if (m_hAccelInPlace != NULL) {
m_hAccelInPlace = NULL;

if (m_hMenuEmbedding != NULL) {
m_hMenuEmbedding = NULL;

if (m_hAccelEmbedding != NULL) {
m_hAccelEmbedding = NULL;

if (m_hMenuInPlaceServer != NULL) {
m_hMenuInPlaceServer = NULL;

if (m_hAccelInPlaceServer != NULL) {
m_hAccelInPlaceServer = NULL;

// Delete shared components from CMultiDocTemplate
if (m_hMenuShared != NULL) {
m_hMenuShared = NULL;

if (m_hAccelTable != NULL) {
m_hAccelTable = NULL;

// Now, reload the resources

This function unloads all of the menu resources that are normally loaded by a CMultiDocTemplate, then calls LoadTemplate to reload them.

Once your app has fixed up the templates, you need to fix up the MainFrame. You probably want to define and send a message indicating a locale change, for example, WM_LOCALE_CHANGE. You can catch that message in the CMainFrame and execute a code snippet like so:

CMenu* pOldMenu = GetMenu();
CMenu NewMenu;
NewMenu.LoadMenu( IDR_MAINFRAME );
SetMenu( &NewMenu );
m_hMenuDefault = NewMenu.Detach();

SendMessageToDescendants( WM_LOCALE_CHANGE );


Your CMDIChildWnd-derived classes will need to catch this message and reset their copies of the menu handles:

LRESULT CMyMDIChildWnd::OnLocaleChanged( WPARAM wParam, LPARAM lParam )
CDocument* pDoc = GetActiveDocument();

if ( pDoc ) {
CMultiDocTemplate* pTemplate = dynamic_cast< CMultiDocTemplate* >( pDoc->GetDocTemplate());

if ( pTemplate ) {
m_hMenuShared = pTemplate->m_hMenuShared;
m_hAccelTable = pTemplate->m_hAccelTable;

return 1;

And that'll do it. Unless you have some modeless dialogs hanging around...
Tags: mfc, microsoft, musings, tech

  • Closer To Fine

    So the cabinets went in today, which is good. There are, sadly, two problems. First, there is a measurement glitch which resulted in the cabinets…

  • This and That

    Gretchen felt pretty lousy today in the wake of the COVID shot and spent most of the day huddled under a blanket on the couch. Neither kid ended up…

  • That Was the Day That Was

    We finished packing out the kitchen last night around midnight and got way too little sleep last night. Then it was up early this morning so that the…

  • Post a new comment


    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded