zoukankan      html  css  js  c++  java
  • vc 国际化的资源文件处理

    MS Windows操作系统是一个世界上广泛使用的操作系统,对于不同语种的国家MS Windows有相应语种的版本。在不同语种的Windows平台上应该运行相应语种的应用程序。也就是说程序的用户界面(如菜单、对话框、状态条)中的提示文字应该使用和Windows操作系统所使用的语种一致。当然英语用户界面的程序可以运行在其它语言平台上,但比较复杂的程序或多或少都有问题,如对话框的尺寸不对,特殊的ASCII字符显示为文字,输入字符串可能会导致死机等。如果不一致却还想使用,则需要动态翻译软件。例如,在英文Windows平台上运行中文版的MS Office就需要像中文之星或四通利方这样的中文动态翻译软件。

      当前国内使用的MS Windows在语种上划分主要有简体中文版和英文版两种。为了让开发的软件能在这两种平台上使用,提出了三种解决方案:第一种解决方案是仅编写中文界面的程序。在中文Windows上程序可以运行(这里的运行是指程序界面不出现乱码),在英文Windows上依靠中文之星或四通利方这样的中文动态翻译软件也可以运行。第二种解决方案是针对中文版和英文版各编一个程序,即在第一种方案的基础上增加了英文版,这样做有两点好处:一是英文Windows平台上运行英文版的软件比英文Windows平台上运行中文版的软件稳定,因为没有像中文之星或四通利方这样的中文动态翻译软件的参与。第三种解决方案是自动根据操作系统的语种选择相应的界面语种。也就是说,同一个软件在中文Windows上显示中文界面,在英文Windows上显示英文界面。这种方案相对于第二种方案的好处在于:程序不用做英文版和中文版两个版本,只要一个版本就可以了,对于用户来说是很方便的。在这三种方案中,前一种是后一种的基础,后一种实现了,前一种也就已经实现了。下面将从易到难介绍三种方案实现的步骤和要点。

      解决方案一、自动生成中文界面框架

      Visual C++6.0版本中可以使用APPWIZARD自动生成具有基本中文界面的WIN32应用程序。使用APPWIZARD时,在自动生成的第一个步骤中,将资源类型选择为简体中文就可以了,可参见图1。其余选项都不涉及语种问题,根据应用程序的具体情况进行选择即可。然后在此基础上作进一步的软件开发工作。

      如果你在一边读文章一边上机实际操作,可能会发现一个问题:不论你怎样设定VisualC++5.0的安装程序的选项,资源类型仅会支持英语、德语、法语、西班牙语和意大利语这五种语言。于是你可能会怀疑你所用的Visual C++5.0版本有问题。实际上并不是Visual C++5.0版本有问题,而是需要从安装盘上手工拷贝一些文件。所需文件在Visual Studio97软件包的第三张包含Visual C++5.0的光盘上。在目录DEVSTUDIO/SHAREDIDE/BIN/IDE下有几个以APPWZ开头的动态链接库(扩展名为dll的文件)。在这些动态链接库中,一个动态链接库提供对一种语言的支持。其中的APPWZCHS.DLL就是支持简体中文的文件。将其拷贝到安装Visual C++5.0的硬盘上相同名字的目录下即可。重新开始自动生成步骤,在自动生成的第一个步骤中,在资源类型选择中将出现简体中文支持。

      解决方案二、支持多种语言

      没有必要从头开发一个英文版。事实上,在现有中文版的基础上生成英文版并不复杂。工作量在于修改资源,程序的代码不用改变。

      图2左边的ResourceView窗口中,同时存在着中英文两种资源,在中文资源的后面标注有“Chinese(P.R.C.)”以示区别。为了保证程序代码不变,相同界面元素的两种语言版本下的标识符必须相同。例如,产品介绍对话框的英文资源的标识符为IDD_ABOUTBOX,中文资源的标识符也应该是IDD_ABOUTBOX。可以用COPY操作对资源进行复制,然后修改语种再修改标识符。 (在资源中用InsertCopy COPY一份资源)

      ResourceView提供的管理功能并不全面,还需要直接编辑资源文件RESOURCE.RC来完成全部任务。经过对RESOURCE.RC文件的研究,发现文件中使用编译控制开关来实现多语言支持。  ......

      //////////////////////////////////////////////////////////////////////////

      // Chinese (P.R.C.) resources

      #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)

      #ifdef _WIN32

      LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

      #pragma code_page(936)

      #endif //_WIN32

      //////////////////////////////////////////////////////////////////////////

      // Dialog

      ......

      /////////////////////////////////////////////////////////////////////////

      // Menu

      ......

      //////////////////////////////////////////////////////////////////////////

      // Icon

      ......

      //////////////////////////////////////////////////////////////////////////

      // Bitmap

      ......

      //////////////////////////////////////////////////////////////////////////

      // Toolbar

      ......

      #ifdef APSTUDIO_INVOKED

      /////////////////////////////////////////////////////////////////////////////

      // TEXTINCLUDE

      1 TEXTINCLUDE DISCARDABLE

      BEGIN

      "resource.h/0"

      END

      2 TEXTINCLUDE DISCARDABLE

      BEGIN

      "#include ""afxres.h""/r/n"

      "/0"

      END

      3 TEXTINCLUDE DISCARDABLE

      BEGIN

      "#define _AFX_NO_SPLITTER_RESOURCES/r/n"

      "#define _AFX_NO_PROPERTY_RESOURCES/r/n"

      "/r/n"

      "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)/r/n"

      "#ifdef _WIN32/r/n"

      "LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED/r/n"

      "#pragma code_page(936)/r/n"

      "#endif/r/n"

      "#include ""res//sample.rc2"" // non-Microsoft Visual C++ edited resources/r/n"

      "#include ""l.chs//afxres.rc"" // Standard components/r/n"

      "#include ""l.chs//afxprint.rc"" // printing/print preview resources/r/n"

      "#include ""l.chs//afxolecl.rc"" // OLE container resources/r/n"

      "#include ""l.chs//afxolesv.rc"" // OLE server resources/r/n"

      "#endif/0"

      END

      #endif // APSTUDIO_INVOKED

      ......

      #endif // Chinese (P.R.C.) resources

      /////////////////////////////////////////////////////////////////////////////

      // English (U.S.) resources

      #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)

      #ifdef _WIN32

      LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

      #pragma code_page(1252)

      #endif //_WIN32

      //////////////////////////////////////////////////////////////////////////

      // Dialog

      ......

      /////////////////////////////////////////////////////////////////////////

      // Menu

      ......

      //////////////////////////////////////////////////////////////////////////

      // Icon

      ......

      //////////////////////////////////////////////////////////////////////////

      // Bitmap

      ......

      //////////////////////////////////////////////////////////////////////////

      // Toolbar

      ......

      /////////////////////////////////////////////////////////////////////////////

      // TEXTINCLUDE

      1 TEXTINCLUDE DISCARDABLE

      BEGIN

      "resource.h/0"

      END

      2 TEXTINCLUDE DISCARDABLE

      BEGIN

      "#include ""afxres.h""/r/n"

      "/0"

      END

      3 TEXTINCLUDE DISCARDABLE

      BEGIN

      "#define _AFX_NO_SPLITTER_RESOURCES/r/n"

      "#define _AFX_NO_PROPERTY_RESOURCES/r/n"

      "/r/n"

      "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)/r/n"

      "#ifdef _WIN32/r/n"

      "LANGUAGE 9, 1/r/n"

      "#pragma code_page(1252)/r/n"

      "#endif/r/n"

      "#include ""res//sample.rc2"" // non-Microsoft Visual C++ edited resources/r/n"

      "#include ""afxres.rc"" // Standard components/r/n"

      "#include ""afxprint.rc"" // printing/print preview resources/r/n"

      "#include ""afxolecl.rc"" // OLE container resources/r/n"

      "#include ""afxolesv.rc"" // OLE server resources/r/n"

      "#endif/0"

      END

      #endif // APSTUDIO_INVOKED

      ......

      #endif // English (U.S.) resources

      /////////////////////////////////////////////////////////////////////////////

      #ifndef APSTUDIO_INVOKED

      /////////////////////////////////////////////////////////////////////////////

      // Generated from the TEXTINCLUDE 3 resource.

      #define _AFX_NO_SPLITTER_RESOURCES

      #define _AFX_NO_PROPERTY_RESOURCES

      #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)

      #ifdef _WIN32

      LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

      #pragma code_page(936)

      #endif

      #include "res/sample.rc2" // non-Microsoft Visual C++ edited resources

      #include "l.chs/afxres.rc" // Standard components

      #include "l.chs/afxprint.rc" // printing/print preview resources

      #include "l.chs/afxolecl.rc" // OLE container resources

      #include "l.chs/afxolesv.rc" // OLE server resources

      #endif

     

      #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)

      #ifdef _WIN32

      LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

      #pragma code_page(1252)

      #endif

      #include "res/sample.rc2" // non-Microsoft Visual C++ edited resources

      #include "afxres.rc" // Standard components

      #include "afxprint.rc" // printing/print preview resources

      #include "afxolecl.rc" // OLE container resources

      #include "afxolesv.rc" // OLE server resources

      #endif

      /////////////////////////////////////////////////////////////////////////////

      #endif // not APSTUDIO_INVOKED

      以上代码中在 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)宏定义后面为中文资源,在#if !defined(AFX_RESOURCE_DLL)|| defined(AFX_TARG_ENU)宏定义后面为英文资源。应该保证中英文资源中都有TEXTINCLUDE段和#ifndef APSTUDIO_INVOKED段。 这样MFC(Microsoft Fundermental Class)缺省资源才会被包含。 对于中文资源来讲,这些额外资源的路径应加上l.chs目录名。

      在编译生成可执行文件时,如果生成中文版本,则在Project Settings对话框中应按图3所示进行设置:在Preprocessor definitions编辑框中加入AFX_TARG_CHS和AFX_RESOURCE_DLL的定义,并且Language选择框中应选择Chinese(P.R.C.)。如果生成英文版本,则在Project Settings对话框中应设置如下:在Preprocessor definitions编辑框中加入AFX_TARG_ENU和AFX_RESOURCE_DLL的定义,并且Language选择框中应选择English(United States)。

    其中AFX_TARG_CHS与936定义了资源文件的简体中文属性。
    英文属性中为AFX_TARG_ENU与1252,
    日文属性中为AFX_TARG_JPN与932,
    繁体中文属性中为AFX_TARG_CHT与950。
    翻译时必须改成相应的语言属性。

    注意下面两句也应改动:
    #include "l.chs//afxres.rc" // Standard components
    #include "l.chs//afxprint.rc" // printing/print preview resources
    英文为:
    #include "afxres.rc" // Standard components
    #include "afxprint.rc" // printing/print preview resources
    日文为:
    #include "l.jpn//afxres.rc" // Standard components
    #include "l.jpn//afxprint.rc" // printing/print preview resources
    繁体中文为:
    #include "l.cht//afxres.rc" // Standard components
    #include "l.cht//afxprint.rc" // printing/print preview resources

      还有一点需要注意,就是所有在代码中显示的文字串都应存储在资源文件中,而不应该在程序中使用硬编码。例如,以下代码就是硬编码:

      ......

      MessageBox(_T("文件没有找到!"),_T("错误")) ;

      ......

      这种提示仅限于Windows简体中文版,而在没有像中文之星、四通利方等翻译软件的Windows英文版平台上显示的将是一堆乱码。正确的方法应该是:

      ......

      Cstring string1, string2 ;

      string1.LoadString(IDS_FILE_NOT_FIND) ;

      string2.LoadString(IDS_ERROR) ;

      MessageBox(string1, string2) ;

      ......

      在中文资源中,IDS_FILE_NOT_FIND对应“文件没有找到!”字符串,IDS_ERROR对应“错误”字符串;在英文资源中IDS_FILE_NOT_FIND对应“File not found! ”字符串,IDS_ERROR对应“Error”字符串。

      三、不同语种平台的自动选择

      实现这项功能的思路是使用纯资源DLL,把应用程序中的资源都放在纯资源DLL中。这种DLL仅含有资源而没有可执行代码,也就是源文件中仅包含RC资源文件。应用程序中中文和英文资源可放在不同的DLL中。例如,中文资源DLL名为CHINESE.DLL,它放置中文资源;英文资源DLL名为ENGLISH.DLL,它放置英文资源。程序启动时根据Windows平台语种的类型,加载相应的DLL。以后资源就会从对应的DLL中读取,从而能保证使用正确的资源.。

      为了实现这项功能,需要在应用程序类中加入一个变量以存储资源DLL的句柄并重载应用程序类中的InitInstance和ExitInstance函数。

      在应用程序类声明中加入代码如下:

      ......

      protected:

      HINSTANCE m_hLangDLL ;

      ......

      在InitInstance函数开始处加入代码如下:

      // Get the primary language identifier

      WORD wLangPID = PRIMARYLANGID(::GetSystemDefaultLangID()) ;

      // Load the language resource DLL

      switch( wLangPID )

      {

      case LANG_ENGLISH:

      m_hLangDLL = ::LoadLibrary("english.dll") ;

      break ;

      case LANG_CHINESE:

      m_hLangDLL = ::LoadLibrary("chinese.dll") ;

      break ;

      }

      if( !m_hLangDLL)

      {

      AfxMessageBox(_T("Unable to load resource DLL!")) ;

      return FALSE ;

      }

      // Tell the application what module contains our resource

      AfxSetResourceHandle(m_hLangDLL) ;

      ......

      在ExitInstance函数开始处加入代码如下:

      // Free language resource library

      if(m_hLangDLL)

      {

      FreeLibrary(m_hLangDLL) ;

      }

      ......

      操作系统所使用的语言由WIN32函数GetSystemDefaultLangID取得。宏PRIMARYLANGID又取出主语言标识符进行判断,选择应该调用的DLL。DLL的加载由WIN32函数LoadLibrary实现。程序中所使用的资源库由AfxSetResourceHandle函数指定。程序退出时用WIN32函数FreeLibrary卸载。

      还有,在编译资源DLL时别忘了在连接时加上/NOENTRY选项以告诉连接器这是一个唯一资源的DLL,不包含程序执行的入口点。

  • 相关阅读:
    LeetCode 226. Invert Binary Tree
    LeetCode 221. Maximal Square
    LeetCode 217. Contains Duplicate
    LeetCode 206. Reverse Linked List
    LeetCode 213. House Robber II
    LeetCode 198. House Robber
    LeetCode 188. Best Time to Buy and Sell Stock IV (stock problem)
    LeetCode 171. Excel Sheet Column Number
    LeetCode 169. Majority Element
    运维工程师常见面试题
  • 原文地址:https://www.cnblogs.com/lidabo/p/3447061.html
Copyright © 2011-2022 走看看