支持 UnicodeWord文档格式.docx
《支持 UnicodeWord文档格式.docx》由会员分享,可在线阅读,更多相关《支持 UnicodeWord文档格式.docx(21页珍藏版)》请在冰点文库上搜索。
![支持 UnicodeWord文档格式.docx](https://file1.bingdoc.com/fileroot1/2023-5/1/fc15695d-6b68-49e8-a237-ed53986f2362/fc15695d-6b68-49e8-a237-ed53986f23621.gif)
根据您的版本定义的符号(即这两个符号中的一个),MFC库的不同变量自动与应用程序链接。
∙类库代码使用可移植的运行时函数和其他方法来确保正确的Unicode或MBCS行为。
∙您仍必须在代码中处理特定类型的国际化任务:
∙使用相同的可移植运行时函数,使MFC在任一环境下可移植。
∙使用_T宏使字符串和字符在任一环境下可移植。
有关更多信息,请参见Tchar.h中的一般文本映射。
∙在MBCS下分析字符串时有一些注意事项。
而在Unicode下分析字符串时则不需要注意这些事项。
有关更多信息,请参见MBCS编程提示。
∙在应用程序中混合使用ANSI(8位)和Unicode(16位)字符时要小心。
可以在程序的某些部分使用ANSI字符,而在其他部分使用Unicode字符,但不能在同一字符串中混合使用这两种字符。
∙在应用程序中不要硬编码字符串。
而应通过将它们添加到应用程序的.rc文件使其成为STRINGTABLE资源。
然后就可以在不必更改或重新编译源代码的情况下本地化应用程序。
有关STRINGTABLE资源的更多信息,请参见字符串编辑器。
欧洲和MBCS字符集的某些字符(如重音字母)的字符代码大于0x80。
由于大多数代码使用有符号字符,因此这些大于0x80的代码在转换为int时是带符号扩展的。
这对数组索引是个问题,因为如果带符号扩展的字符为负值,则索引将超出数组范围。
使用MBCS(如日语)的语言也很独特。
由于一个字符可能由单字节或双字节组成,因此应始终同时处理两个字节。
3、国际化策略
根据您的目标操作系统和市场,有几个国际化策略:
∙应用程序使用Unicode,因此在Windows2000和WindowsNT(但不能在Windows95或Windows98)上运行。
使用Unicode特定的功能并且所有字符都为16位宽(尽管可以出于特殊目的在程序的某些部分使用ANSI字符)。
C运行时库提供仅使用Unicode编程的函数、宏和数据类型。
MFC则完全支持Unicode。
∙如果应用程序使用MBCS则可以在任何Win32平台上运行。
使用特定于MBCS的功能。
字符串可以包含单字节字符、双字节字符或同时包含这两种字符。
C运行时库提供仅使用MBCS编程的函数、宏和数据类型。
MFC则完全支持MBCS。
∙编写的应用程序的源代码具有完全可移植性。
通过定义_UNICODE符号或_MBCS符号来重新编译应用程序,可以生成使用其中任何一种字符的版本。
∙应用程序对Windows95、Windows98和WindowsME上缺少的Unicode函数使用包装库,类似设计一个在Windows98和Windows2000上都运行的Unicode应用程序中所描述的包装库。
包装库还可通过商业手段获得。
使用完全可移植的C运行时函数、宏和数据类型。
MFC的灵活性支持所有这些策略。
这些主题的其余部分着重说明如何编写可生成为Unicode应用程序或MBCS应用程序的完全可移植代码。
4、区域设置和代码页
区域设置ID反映特定地理区域的当地约定和语言。
可能有一个以上的国家/地区说某种特定的语言,例如,巴西和葡萄牙都说葡萄牙语。
反之,一个国家/地区可能有一种以上的官方语言。
例如,加拿大有两种官方语言:
英语和法语。
因此,加拿大有两个不同的区域设置:
加拿大英语和加拿大法语。
一些与区域设置相关的类别包括日期的格式设置和货币值的显示格式。
语言确定文本和数据的格式约定,而国家/地区则确定区域约定。
每种语言都有一个由代码页表示的唯一映射,包括字母表中的字符以外的字符(如标点符号和数字)。
代码页是一个字符集并且与语言相关。
因此,区域设置就成为语言、国家/地区和代码页的唯一组合。
可以通过调用setlocale函数在运行时更改区域设置和代码页设置。
不同的语言可能使用不同的代码页。
例如,ANSI代码页1252用于英语和大多数欧洲语言,而ANSI代码页932则用于日本汉字。
实际上,所有代码页都共享ASCII字符集中最低的128个字符(0x00到0x7F)。
任何单字节代码页都可使用一个包含256项的表来表示,在该表中表示为字节值到字符(包括数字和标点符号)或标志符号的映射。
任何多字节代码页也可以表示为一个非常大的表(有64K项),包含双字节值到字符的映射。
但实际上,对于前256个(单字节)字符,它通常用表表示;
对于双字节值,则用范围表示。
有关代码页的更多信息,请参见代码页。
C运行时库有两类内部代码页:
区域设置和多字节。
在程序执行期间可以更改当前代码页(有关setlocale和_setmbcp函数的信息,请参见文档)。
而且,运行时库可以获取并使用操作系统代码页的值。
在Windows2000中,操作系统代码页是“系统默认ANSI”代码页。
此代码页在程序的执行期间保持不变。
更改区域设置代码页后,与区域设置相关的函数集的行为更改为由选定的代码页指示的行为。
默认情况下,所有与区域设置相关的函数使用对于“C”区域设置唯一的区域设置代码页开始执行过程。
可以通过调用setlocale函数来更改内部区域设置代码页(以及其他区域设置特定的属性)。
对setlocale(LC_ALL,"
"
)的调用将区域设置设置为由操作系统用户区域设置指示的那个区域设置。
同样,更改多字节代码页时,多字节函数的行为更改为由选定的代码页指示的行为。
默认情况下,所有多字节函数使用与操作系统默认代码页相对应的多字节代码页开始执行过程。
可以通过调用_setmbcp函数来更改内部多字节代码页。
C运行时函数setlocale设置、更改或查询部分或全部当前程序的区域设置信息。
_wsetlocale例程是setlocale的宽字符版本;
_wsetlocale的参数和返回值是宽字符字符串。
5、字符集可移植性的好处
即使目前不打算国际化应用程序,也可以从使用MFC和C运行时可移植性功能中获益:
∙编写可移植代码使基本代码更灵活。
以后可以很容易地将代码移动到Unicode或MBCS。
∙使用Unicode能提高用于Windows2000的应用程序的效率。
由于Windows2000使用Unicode,因此与操作系统之间传递的非Unicode字符串必须进行转换,这会增加系统开销。
∙使用MBCS使您得以在Windows2000以外的Win32平台(如Windows95或Windows98)上支持国际市场。
6、支持使用wmain
VisualC++支持定义wmain函数,并将宽字符参数传递给Unicode应用程序。
使用与main函数相似的格式声明wmain函数的形参。
然后可以将宽字符参数和宽字符环境指针(可选)传递给该程序。
wmain的argv和envp参数为wchar_t*类型。
例如:
复制代码
wmain(int
argc,wchar_t
*argv[
],wchar_t
*envp[
]
)
MFCUnicode应用程序使用wWinMain作为入口点。
在这种情况下,CWinApp:
:
m_lpCmdLine是一个Unicode字符串。
请务必使用/ENTRY链接器选项设置wWinMainCRTStartup。
如果程序使用main函数,则多字节字符环境由运行时库在程序启动时创建。
环境的宽字符副本仅在需要时创建(如调用_wgetenv或_wputenv函数时)。
首次调用_wputenv或在MBCS环境已存在的情况下首次调用_wgetenv时,将创建相应的宽字符字符串环境。
然后用_wenviron全局变量(_environ全局变量的宽字符版本)指向该环境。
此时,同时存在两个环境的副本(MBCS和Unicode),在程序的整个生存期这两个副本由运行时系统维护。
同样,如果程序使用wmain函数,则在程序启动时创建宽字符环境并用_wenviron全局变量指向该环境。
在首次调用_putenv或getenv时创建MBCS(ASCII)环境,并用_environ全局变量指向该环境。
7、支持Unicode
Unicode是支持所有字符集(包括无法以单个字节表示的字符集)的规范。
为国际市场编程时应考虑使用Unicode或多字节字符集(MBCS),或使程序能够通过更改开关来生成支持两种字符集之一的程序。
宽字符是双字节多语言字符代码。
在当今的全球计算业内使用的大多数字符(包括技术符号和特殊的发布字符),都可以根据Unicode规范表示为宽字符形式。
无法以1个宽字符表示的字符可以通过Unicode的代理项功能以Unicode对表示。
由于每个宽字符总是以固定的16位大小表示,因此使用宽字符可以简化使用国际字符集进行的编程。
宽字符字符串表示为一个wchar_t[]数组并由wchar_t*指针指向它。
可以通过用字母L作为字符的前缀将任何ASCII字符表示为宽字符形式。
例如,L'
\0'
是终止宽(16位)NULL字符。
同样,可以通过用字母L作为ASCII字符串的前缀(L"
Hello"
)将任何ASCII字符串表示为宽字符字符串形式。
通常,宽字符在内存中占用的空间比多字节字符多,但处理速度更快。
另外,在多字节编码中一次只能表示一个区域设置,而世界上的所有字符集都同时以Unicode表示形式表示。
除数据库类外,MFC框架完全支持Unicode。
(ODBC不支持Unicode。
)MFC通过始终使用可移植的宏来实现对Unicode的支持,如下表所示:
MFC中的可移植数据类型
不可移植的数据类型
由该宏替换
char
_TCHAR
char*,LPSTR(Win32数据类型)
LPTSTR
constchar*,LPCSTR(Win32数据类型)
LPCTSTR
CString类使用_TCHAR作为基,并提供构造函数和运算符以方便转换。
可以通过使用与处理WindowsANSI字符集相同的逻辑来编写大多数Unicode的字符串操作(只是基本操作单位是16位字符,而非8位字节)。
与使用多字节字符集(MBCS)不同,不必(也不应)将Unicode字符视为两个不同的字节。
2、Unicode编程摘要
若要利用MFC和C运行时对Unicode的支持,需要:
∙定义_UNICODE。
在生成程序之前定义_UNICODE符号。
∙指定入口点。
在项目的属性页对话框的“链接器”文件夹的“输出”页中,设置wWinMainCRTStartup的“入口点”符号。
∙使用可移植的运行时函数和类型。
为Unicode字符串处理使用正确的C运行时函数。
可以使用wcs函数族,但您可能更喜欢使用完全可移植的(支持国际化的)_TCHAR宏。
这些宏都以_tcs为前缀;
它们一对一地替换str函数族。
在“运行时库参考”的国际化节中对这些函数有详细介绍。
使用支持Unicode中描述的_TCHAR和相关的可移植数据类型。
∙正确地处理字符串。
VisualC++编译器将编码的字符串解释为:
L"
thisisaliteralstring"
指出这是Unicode字符的字符串。
可以对文字字符使用相同的前缀。
一般使用_T宏对字符串进行编码,因此在Unicode下字符串编译为Unicode字符串,不使用Unicode时字符串编译为ANSI字符串(包括MBCS)。
例如,不要使用:
pWnd->
SetWindowText("
);
而使用:
SetWindowText(_T("
));
使用已定义的_UNICODE,_T将字符串翻译为以L为前缀的格式;
否则_T将字符串翻译为不带L前缀的格式。
提示
_T宏与_TEXT宏相同。
∙将字符串长度传递给函数时要小心。
一些函数需要获取字符串的字符数;
另一些函数需要获取字符串的字节数。
例如,如果已定义_UNICODE,则下列对CArchive对象的调用无效(str属于CString):
archive.Write(str,str.GetLength());
//invalid
在Unicode应用程序中,由于每个字符都是2个字节宽,因此长度给出的是字符数而不是正确的字节数。
所以必须使用:
archive.Write(str,str.GetLength()*sizeof(_TCHAR));
//valid
它指定要写入的正确字节数。
但是,MFC成员函数是面向字符而非面向字节的,因此无需此额外的编码:
pDC->
TextOut(str,str.GetLength());
CDC:
TextOut采用字符数而非字节数。
∙使用fopen_s,_wfopen_s打开Unicode文件。
总之,MFC和运行时库对Windows2000下的Unicode编程提供下列支持:
∙除数据库类成员函数外,所有MFC函数(包括CString)都支持Unicode。
CString还提供Unicode/ANSI转换函数。
∙运行时库提供所有字符串处理函数的Unicode版本。
(运行时库还提供适合Unicode或MBCS的可移植版本。
这些版本是_tcs宏。
∙Tchar.h提供可移植的数据类型以及用于转换字符串和字符的_T宏。
∙运行时库提供main的宽字符版本。
使用wmain可使应用程序成为Unicode识别的应用程序。
3、Tchar.h中的一般文本映射
为简化代码传输以方便国际使用,Microsoft运行时库为许多数据类型、例程和其他对象提供Microsoft特定的“一般文本”映射。
您可以使用Tchar.h中定义的这些映射,根据使用#define语句定义的清单常数,编写可以为单字节、多字节或Unicode编译的一般代码。
一般文本映射是与ANSI不兼容的Microsoft扩展。
使用Tchar.h可以从同一个源中生成单字节、MBCS和Unicode应用程序。
Tchar.h定义以_tcs为前缀的宏,这些宏根据正确的预处理器定义映射到适当的str、_mbs或wcs函数。
若要生成MBCS,请定义_MBCS符号。
若要生成Unicode,请定义_UNICODE符号。
若要生成单字节应用程序,请不进行任何定义(默认)。
默认情况下,为MFC应用程序定义的是_MBCS。
在Tchar.h中根据条件定义_TCHAR数据类型。
如果为您的版本定义了_UNICODE符号,则_TCHAR被定义为wchar_t;
否则,对于单字节和MBCS版本,_TCHAR被定义为char。
((wchar_t是基本的Unicode宽字符数据类型,它是8位有符号char的16位对等项。
)对于国际应用程序,使用以_TCHAR(而非字节)为单位进行操作的_tcs函数族。
例如,_tcsncpy复制n个_TCHAR,而不是n个字节。
由于某些SBCS字符串处理函数采用(有符号的)char*参数,因此定义_MBCS时将产生类型不匹配的编译器警告。
有三种方法避免此警告,按效率高低的顺序依次为:
1.在Tchar.h中使用类型安全内联函数thunk。
这是默认行为。
2.通过在命令行上定义_MB_MAP_DIRECT,在Tchar.h中使用直接宏。
如果这样做,必须手动匹配类型。
这是最快的方法,但不是类型安全的方法。
3.在Tchar.h中使用“类型安全”静态链接库函数thunk。
若要这样做,请在命令行上定义_NO_INLINING常数。
这是最慢的方法,但却是类型安全性最高的方法。
一般文本映射的预处理器指令
#define
编译版本
示例
_UNICODE
Unicode(宽字符)
_tcsrev映射到_wcsrev
_MBCS
多字节字符
_tcsrev映射到_mbsrev
无(默认:
既未定义_UNICODE也未定义_MBCS)
SBCS(ASCII)
_tcsrev映射到strrev
例如,如果在程序中定义了_MBCS,则Tchar.h中定义的一般文本函数_tcsrev映射到_mbsrev。
或者如果在程序中定义了_UNICODE,则_tcsrev映射到_wcsrev。
否则_tcsrev映射到strrev。
在Tchar.h中还提供了其他数据类型映射以方便编程,但_TCHAR是最有用的。
一般文本数据类型映射
一般文本数据类型名称
_UNICODE和_MBCS未定义
_MBCS已定义
_UNICODE已定义
_TCHAR
wchar_t
_TINT
int
wint_t
_TSCHAR
signedchar
_TUCHAR
unsignedchar
_TXCHAR
_T或_TEXT
无效(由预处理器移除)
L(将后面的字符或字符串转换成相应的Unicode形式)
有关例程、变量和其他对象的一般文本映射的完整列表,请参见“运行时库参考”中的一般文本映射。
Unicode字符串有可能包含嵌入空字节,所以不要在Unicode字符串中使用str函数族。
同样道理,不要在MBCS(或SBCS)字符串中使用wcs函数族。
下列代码片段阐释了有关映射到MBCS、Unicode和SBCS模型的_TCHAR和_tcsrev的用法。
_TCHAR*RetVal,*szString;
RetVal=_tcsrev(szString);
如果已定义_MBCS,则预处理器将此片段映射到下列代码:
char*RetVal,*szString;
RetVal=_mbsrev(szString);
如果已定义_UNICODE,则预处理器将此片段映射到下列代码:
wchar_t*RetVal,*szString;
RetVal=_wcsrev(szString);
如果既未定义_MBCS也未定义_UNICODE,则预处理器将此片段映射到单字节ASCII代码:
RetVal=strrev(szString);
因此可以编写、维护和编译与三种字符集中任何一种的特定例程一起运行的单个源代码文件。
4、Internationalization
usingnamespaceSystem;
usingnamespaceSystem:
Collections;
Globalization;
intmain()
{
//CreatesandinitializestheCultureInfowhichusestheinternationalsort.
CultureInfo^myCIintl=gcnewCultureInfo("
es-ES"
false);
//CreatesandinitializestheCultureInfow