KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q147149: HOWTO: Localize Application Resources with Foundation Classes

Article: Q147149
Product(s): Microsoft C Compiler
Version(s): winnt:1.0,2.0,2.1,2.2
Operating System(s): 
Keyword(s): kbcode kbMFC kbResourceEd kbVC100 kbVC150 kbVC200 kbVC220 kbLocalization kbGrpDSMFCATL
Last Modified: 06-MAY-2001

-------------------------------------------------------------------------------
The information in this article applies to:

- The Microsoft Foundation Classes (MFC), included with:
   - Microsoft Visual C++ for Windows, 16-bit edition, versions 1.0, 1.5, 1.51, 1.52 
   - Microsoft Visual C++, 32-bit Editions, versions 1.0, 2.0, 2.1, 2.2 
-------------------------------------------------------------------------------


SUMMARY
=======

Microsoft Foundation Class Library Technical Note 23 explains how to customize
standard framework resources, such as the buttons on a print preview dialog bar.
However, this technical note does not provide a good solution for developers who
are producing an application localized into more than one language, and there is
a problem with the method described.

When localizing an application for several languages, it is most convenient to
place all of the application's resources into a dynamic link library (DLL). To
localize the application into a new language, clone the DLL and translate the
resources into the appropriate language. After testing, you can ship the
application code with the appropriate language-specific DLL to address each
market.

The remainder of this article outlines the general steps required to localize an
application by moving the resources into a DLL.

MORE INFORMATION
================

To place all application resources into a DLL project, open the .rc file in App
Studio. Choose "Save As" (without the quotation marks) from the "File" (without
the quotation marks) menu to store the resources into another directory (created
for this purpose). Then open the original .rc file, and remove all resources
visible in the App Studio Resource Browser. Finally, choose "Set Includes"
(without the quotation marks) from the App Studio "File" (without the quotation
marks) menu. Delete the #include statements for Afxprint.rc and for Afxres.rc
from the Compile-Time Directives list and choose "OK" (without the quotation
marks).

Use the Visual Workbench to create a new Windows DLL project for the resources.
Set the project type to Windows dynamic-link library, and clear the "Use
Microsoft Foundation Classes" check box. Add the .rc file to the project. Then
create the following files in your DLL directory, and add them to the project.

Mylocal.cpp
-----------

  #include <windows.h>

  int CALLBACK LibMain(HINSTANCE hinst, WORD wDataSeg, WORD cbHeap,
        LPSTR lpszCmdLine )
  {
     return 1;
  }

Mylocal.def
-----------

  LIBRARY      MYLOCAL
  DESCRIPTION  'Localized resources for MFC application'
  EXETYPE      WINDOWS

  CODE         PRELOAD MOVEABLE DISCARDABLE
  DATA         PRELOAD MOVEABLE SINGLE

  SEGMENTS
     WEP_TEXT FIXED PRELOAD

  EXPORTS
     WEP @1 RESIDENTNAME ; required WEP entry point
                         ; (uses library WEP routine)

Copy the standard framework resources into the .rc file for your DLL so you can
modify them. Technical Note 23 outlines a procedure to do this. To copy all
resources from Afxprint.rc and Afxres.rc into the .rc file for your DLL, select
the resources in each source file. Then press and hold the CTRL key and drag the
resources into the new .rc file. Edit the Compile- Time Directives list box in
App Studio to remove the #include files.

There are two problems with this procedure. Perform the following two steps to
work around these problems before compiling your DLL:

NOTE: In MFC version 2.5 and later, step 1 is no longer necessary.

1. The AFX_IDC_MAGNIFY cursor, used by print preview, is loaded using the
  AfxGetInstanceHandle() function rather than the AfxGetResourceHandle()
  function. This error occurs on line 904 of the Viewprev.cpp file in the
  Microsoft Foundation Class Library source directory (by default,
  C:\Msvc\Mfc\Src). If you wish, you can modify the source code and recompile
  the libraries. However, a reasonable method to work around this problem
  involves copying the AFX_IDC_MAGNIFY resource into your application's .rc
  file. Only this resource would be common to all languages.

2. The Afxprint.rc file (located by default in the C:\Msvc\Mfc\Include
  directory) declares AFX_IDD_PREVIEW_TOOLBAR, the standard framework resource
  for the print preview CDialogBar, with the following resource style:

        STYLE WS_CHILD | CBRS_TOP

  The problem is that the CBRS_TOP style is specific to the Microsoft Foundation
  Class Library; App Studio does not copy this style when you follow the
  procedure in Technical Note 23. Use a text editor to open the .rc file as a
  text file. (Note that you may need to change an option in the Editor Options
  dialog box in Visual Workbench.) Add the vertical bar (the OR symbol) and
  CBRS_TOP to the STYLE statement. Otherwise, the print preview dialog bar does
  not appear.

AppWizard creates the .rc2 file in the DLL Res directory to contain version
information for the application. Edit this information as appropriate for your
DLL.

Build the DLL project and copy it into your application's directory.

To use the localized resources in the DLL from your application, add the
following code to your application and rebuild it:

1. Modify the main application class (for example, CMyApp) to add an HINSTANCE
  member variable to contain the DLL instance handle, as follows:

     HINSTANCE m_hInstDLL;

2. In CMyApp::InitInstance(), insert the following code before the first line of
  code generated by ClassWizard:

     if ((m_hInstDLL = ::LoadLibrary("mylocal.dll")) < HINSTANCE_ERROR)
     {
        return FALSE; // failed to load the localized resources
     }
     else
     {
        AfxSetResourceHandle(m_hInstDLL); // get resources from the DLL
     }

3. Modify the CMyApp::ExitInstance() function to free the library before the
  application exits. Modify the function as follows:

     int CMyApp::ExitInstance()
     {
        FreeLibrary(m_hInstDLL);
        return CWinApp::ExitInstance();
     }

WARNING: You might encounter a problem if you follow the advice in step 3. For
additional information, please see the following article in the Microsoft
Knowledge Base:

  Q187684 BUG: Assert When Calling AfxFreeLibrary from ExitInstance

Once you establish that the application works as expected, you can use App Studio
to translate the resources in the DLL project and make additional copies of the
project to localize for other languages.

For more information on this procedure, see the Microsoft Foundation Class
Library Technical Notes. The Visual C++ 1.0 for Windows setup program creates an
MFC Tech Notes icon in the Visual C++ 1.0 group.

Additional query words: kbdsupport

======================================================================
Keywords          : kbcode kbMFC kbResourceEd kbVC100 kbVC150 kbVC200 kbVC220 kbLocalization kbGrpDSMFCATL 
Technology        : kbAudDeveloper kbMFC
Version           : winnt:1.0,2.0,2.1,2.2
Issue type        : kbhowto

=============================================================================

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.