Windows核心编程002.pdf
《Windows核心编程002.pdf》由会员分享,可在线阅读,更多相关《Windows核心编程002.pdf(16页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载第2章U n i c o d e随着M i c r o s o f t公司的Wi n d o w s操作系统在全世界日益广泛的流行,对于软件开发人员来说,将目标瞄准国际上的各个不同市场,已经成为一个越来越重要的问题。美国的软件版本比国际版本提前6个月推向市场,这曾经是个司空见惯的现象。但是,由于各国对 Wi n d o w s操作系统提供了越来越多的支持,因此就更加容易为国际市场生产各种应用软件,从而缩短了软件的美国版本与国际版本推出的时间间隔。Wi n d o w s操作系统始终不逾地提供各种支持,以帮助软件开发人员进行应用程序的本地化工作。应用软件可以从各种不同的函数中获得特定国家的信
2、息,并可观察控制面板的设置,以确定用户的首选项。Wi n d o w s甚至支持不同的字体,以适应应用的需要。之所以将这一章放在本书的开头,是因为考虑到 U n i c o d e是开发任何应用程序时要采用的基本步骤。本书的每一章中几乎都要讲到关于 U n i c o d e的问题,而且书中给出的所有示例应用程序都是“用U n i c o d e实现的”。如果你为Microsoft Windows 2000或Microsoft Windows CE开发应用程序,你应该使用U n i c o d e进行开发。如果你为Microsoft Windows 98开发应用程序,你必须对某些问题作出决定。
3、本章也要讲述Windows 98的有关问题。2.1 字符集软件的本地化要解决的真正问题,实际上就是如何来处理不同的字符集。多年来,许多人一直将文本串作为一系列单字节字符来进行编码,并在结尾处放上一个零。对于我们来说,这已经成了习惯。当调用s t r l e n函数时,它在以0结尾的单字节字符数组中返回字符的数目。问题是,有些文字和书写规则(比如日文中的汉字就是个典型的例子)的字符集中的符号太多了,因此单字节(它提供的符号最多不能超过 2 5 6个)是根本不敷使用的。为此出现了双字节字符集(D B C S),以支持这些文字和书写规则。2.1.1 单字节与双字节字符集在双字节字符集中,字符串中的每
4、个字符可以包含一个字节或包含两个字节。例如,日文中的汉字,如果第一个字符在 0 x 8 1与0 x 9 F之间,或者在0 x E 0与0 x F C之间,那么就必须观察下一个字节,才能确定字符串中的这个完整的字符。使用双字节字符集,对于程序员来说简直是个很大的难题,因为有些字符只有一个字节宽,而有些字符则是两个字节宽。如果只是调用s t r l e n函数,那么你无法真正了解字符串中究竟有多少字符,它只能告诉你到达结尾的0之前有多少个字节。A N S I的C运行期库中没有配备相应的函数,使你能够对双字节字符集进行操作。但是,Microsoft Visual C+的运行期库却包含许多函数,如_
5、m b s l e n,它可以用来操作多字节(既包括单字节也包括双字节)字符串。为了帮助你对D B C S字符串进行操作,Wi n d o w s提供了下面的一组帮助函数(见表2-1)。前两个函数CharNext 和Char Prev 允许前向或逆向遍历DBCS 字符串,方法是每次一个字符。第三个函数 IsDBCSLeadByte,在字节返回到一个两字字节符的第一个字节时将返回T R U E。表2-1 对D B C S字符串进行操作的帮助函数函数描述PTSTR CharNext(PCTSTR pszCurrentChar);返回字符串中的下一个字符的地址PTSTR CharPrev(PCTST
6、R pszStart,PCTSTR 返回字符串中的上一个字符的地址p s z C u r r e n t C h a r);BOOL IsDBCSLeadByteTRUE(BYTE bTestChar);如果该字节是DBCS字符的第一个字节,则返回尽管这些函数使得我们对 D B C S的操作更容易,但还需要,一个更好的方法让我们来看看U n i c o d e。2.1.2 Unicode:宽字节字符集U n i c o d e是A p p l e和X e r o x公司于1 9 8 8年建立的一个技术标准。1 9 9 1年,成立了一个集团机构负责U n i c o d e的开发和推广应用。该集
7、团由A p p l e、C o m p a q、H P、I B M、M i c r o s o f t、O r a c l e、Silicon Graphics,Inc.、S y b a s e、U n i s y s和X e r o x等公司组成(若要了解该集团的全部成员,请通过网址w w w.U n i c o d e.o rg查找)。该集团负责维护U n i c o d e标准。U n i c o d e的完整描述可以参阅A d d i s o n We s l e y出版的Unicode Standard一书(该书可以通过网址w w w.U n i c o d e.o rg订购)。U
8、n i c o d e提供了一种简单而又一致的表示字符串的方法。U n i c o d e字符串中的所有字符都是1 6位的(两个字节)。它没有专门的字节来指明下一个字节是属于同一个字符的组成部分,还是一个新字符。这意味着你只需要对指针进行递增或递减,就可以遍历字符串中的各个字符,不再需要调用C h a r N e x t、C h a r P r e v和I s D B C S L e a d B y t e之类的函数。由于U n i c o d e用一个1 6位的值来表示每个字符,因此总共可以得到 65 000个字符,这样,它就能够对世界各国的书面文字中的所有字符进行编码,远远超过了单字节字符
9、集的 2 5 6个字符的数目。目前,已经为阿拉伯文、中文拼音、西里尔字母(俄文)、希腊文、西伯莱文、日文、韩文和拉丁文(英文)字母定义了 U n i c o d e代码点。这些字符集中还包含了大量的标点符号、数学符号、技术符号、箭头、装饰标志、区分标志和其他许多字符。如果将所有这些字母和符号加在一起,总计约达3 5 0 0 0个不同的代码点,这样,总计 65 000多个代码点中,大约还有一半可供将来扩充时使用。这65 536个字符可以分成不同的区域。表 2-2 显示了这样的区域的一部分以及分配给这些区域的字符。表2-2 区域字符1 6位代码字符16 位 代 码字符0 0 0 0-0 0 7 F
10、A S C I I0 3 0 0-0 3 6 F通用区分标志0 0 8 0-0 0 F F拉丁文1字符0 4 0 0-0 4 F F西里尔字母0 1 0 0-0 1 7 F欧洲拉丁文0 5 3 0-0 5 8 F亚美尼亚文0 1 8 0-0 1 F F扩充拉丁文0 5 9 0-0 5 F F西伯莱文0 2 5 0-0 2 A F标准拼音0 6 0 0-0 6 F F阿拉伯文0 2 B 0-0 2 F F修改型字母0 9 0 0-0 9 7 F梵文目前尚未分配的代码点大约还有29 000个,不过它们是保留供将来使用的。另外,大约有6 0 0 0个代码点是保留供个人使用的。12计计第一部分程序员必
11、读下载代码点是字符集中符号的位置。2.2 为什么使用U n i c o d e当开发应用程序时,当然应该考虑利用 U n i c o d e的优点。即使现在你不打算对应用程序进行本地化,开发时将U n i c o d e放在心上,肯定可以简化将来的代码转换工作。此外,U n i c o d e还具备下列功能:可以很容易地在不同语言之间进行数据交换。使你能够分配支持所有语言的单个二进制.e x e文件或D L L文件。提高应用程序的运行效率(本章后面还要详细介绍)。2.3 Windows 2000与U n i c o d eWindows 2000是使用U n i c o d e从头进行开发的,
12、用于创建窗口、显示文本、进行字符串操作等的所有核心函数都需要 U n i c o d e字符串。如果调用任何一个 Wi n d o w s函数并给它传递一个A N S I字符串,那么系统首先要将字符串转换成 U n i c o d e,然后将U n i c o d e字符串传递给操作系统。如果希望函数返回 A N S I字符串,系统就会首先将 U n i c o d e字符串转换成A N S I字符串,然后将结果返回给你的应用程序。所有这些转换操作都是在你看不见的情况下发生的。当然,进行这些字符串的转换需要占用系统的时间和内存。例如,如果调用C r e a t e Wi n d o w E x
13、函数,并传递类名字和窗口标题文本的非U n i c o d e字符串,那么C r e a t e Wi n d o w E x必须分配内存块(在你的进程的默认堆中),将非U n i c o d e字符串转换成U n i c o d e字符串,并将结果存储在分配到的内存块中,然后调用U n i c o d e版本的C r e a t e Wi n d o w E x函数。对于用字符串填入缓存的函数来说,系统必须首先将 U n i c o d e字符串转换成非U n i c o d e字符串,然后你的应用程序才能处理该字符串。由于系统必须执行所有这些转换操作,因此你的应用程序需要更多的内存,并且运
14、行的速度比较慢。通过从头开始用 U n i c o d e来开发应用程序,就能够使你的应用程序更加有效地运行。2.4 Windows 98与U n i c o d eWindows 98不是一种全新的操作系统。它继承了1 6位Wi n d o w s操作系统的特性,它不是用来处理U n i c o d e的。如果要增加对U n i c o d e的支持,其工作量非常大,因此在该产品的特性列表中没有包括这个支持项目。由于这个原因,Windows 98像它的前任产品一样,几乎都是使用A N S I字符串来进行所有的内部操作的。仍然可以编写用于处理U n i c o d e字符和字符串的Wi n d
15、 o w s应用程序,不过,使用Wi n d o w s函数要难得多。例如,如果想要调用 C r e a t e Wi n d o w E x函数并将A N S I字符串传递给它,这个调用的速度非常快,不需要从你进程的默认堆栈中分配缓存,也不需要进行字符串转换。但是,如果想要调用C r e a t e Wi n d o w E x函数并将U n i c o d e字符串传递给它,就必须明确分配缓存,并调用函数,以便执行从U n i c o d e到A N S I字符串的转换操作。然后可以调用 C r e a t e Wi n d o w E x,传递A N S I字符串。当C r e a t
16、e Wi n d o w E x函数返回时,就能释放临时缓存。这比使用 Windows 2000上的U n i c o d e要麻烦得多。本章的后面要介绍如何在Windows 98下进行这些转换。虽然大多数U n i c o d e函数在Windows 98中不起任何作用,但是仍有少数U n i c o d e函数确实非常有用。这些函数是:E n u m R e s o u r c e L a n g u a g e s WG e t Te x t E x t e n t P o i n t 3 2 WE n u m R e s o u r c e N a m e s WG e t Te x
17、t E x t e n t P o i n t W第 2章 Unicode计计13下载E n u m R e s o u r c e Ty p e s WL s t r l e n WE x t Te x t O u t WM e s s a g e B o x E xWF i n d R e s o u r c e WM e s s a g e B o x WF i n d R e s o u r c e E x WTe x t O u t WG e t C h a r Wi d t h WWi d e C h a r To M u l t i B y t eG e t C o m m a
18、n d L i n e WM u l t iBy t e To Wi d e C h a r可惜的是,这些函数中有许多函数在Windows 98中会出现各种各样的错误。有些函数无法使用某些字体,有些函数会破坏内存堆栈,有些函数会使打印机驱动程序崩溃,等等。如果要使用这些函数,必须对它们进行大量的测试。即使这样,可能仍然无法解决问题。因此必须向用户说明这些情况。2.5 Windows CE与U n i c o d eWindows CE操作系统是为小型设备开发的,这些设备的内存很小,并且不带磁盘存储器。你可能认为,由于 M i c r o s o f t公司的主要目标是建立一种尽可能小的操作系统
19、,因此它会使用A N S I作为自己的字符集。但是M i c r o s o f t公司并非鼠目寸光,他们懂得,Windows CE的设备要在世界各地销售,他们希望降低软件开发成本,这样就能更加容易地开发应用程序。为此,Windows CE本身就是使用U n i c o d e的一种操作系统。但是,为了使Windows CE尽量做得小一些,M i c r o s o f t公司决定完全不支持ANSI Wi n d o w s函数。因此,如果要为Windows CE开发应用程序,必须懂得U n i c o d e,并且在整个应用程序中使用U n i c o d e。2.6 需要注意的问题下面让我
20、们进一步明确一下“M i c r o s o f t公司对U n i c o d e支持的情况”:Windows 2000既支持U n i c o d e,也支持A N S I,因此可以为任意一种开发应用程序。Windows 98只支持A N S I,只能为A N S I开发应用程序。Windows CE只支持U n i c o d e,只能为U n i c o d e开发应用程序。虽然M i c r o s o f t公司试图让软件开发人员能够非常容易地开发在这 3种平台上运行的软件,但是U n i c o d e与A N S I之间的差异使得事情变得困难起来,并且这种差异通常是我遇到的最大
21、的问题之一。请不要误解,M i c r o s o f t公司坚定地支持U n i c o d e,并且我也坚决鼓励你使用它。不过你应该懂得,你可能遇到一些问题,需要一定的时间来解决这些问题。建议你尽可能使用U n i c o d e。如果运行Windows 98,那么只有在必要时才需转换到A N S I。不过,还有另一个小问题你应该了解,那就是C O M。2.7 对C O M的简单说明当M i c r o s o f t公司将C O M从1 6位Wi n d o w s转换成Wi n 3 2时,公司作出了一个决定,即需要字符串的所有C O M接口方法都只能接受U n i c o d e字符串
22、。这是个了不起的决定,因为C O M通常用于使不同的组件能够互相进行通信,而U n i c o d e则是传递字符串的最佳手段。如果你为Windows 2000或Windows CE开发应用程序,并且也使用C O M,那么你将会如虎添翼。在你的整个源代码中使用U n i c o d e,将使与操作系统进行通信和与C O M对象进行通信的操作变成一件轻而易举的事情。如果你为Windows 98开发应用程序,并且也使用C O M,那么将会遇到一些问题。C O M要14计计第一部分程序员必读下载求使用U n i c o d e字符串,而操作系统的大多数函数要求使用 A N S I字符串。那是多么难办
23、的事情啊!我曾经从事过若干个项目的开发,在这些项目中,我编写了许多代码,仅仅是为了来回进行字符串的转换。2.8 如何编写U n i c o d e源代码M i c r o s o f t公司为U n i c o d e设计了Windows API,这样,可以尽量减少对你的代码的影响。实际上,你可以编写单个源代码文件,以便使用或者不使用 U n i c o d e来对它进行编译。只需要定义两个宏(U N I C O D E和_ U N I C O D E),就可以修改然后重新编译该源文件。2.8.1 C运行期库对U n i c o d e的支持为了利用U n i c o d e字符串,定义了一些
24、数据类型。标准的 C头文件S t r i n g.h已经作了修改,以便定义一个名字为w c h a r _ t的数据类型,它是一个U n i c o d e字符的数据类型:例如,如果想要创建一个缓存,用于存放最多为 9 9个字符的U n i c o d e字符串和一个结尾为零的字符,可以使用下面这个语句:该语句创建了一个由 1 0 0个1 6位值组成的数组。当然,标准的 C运行期字符串函数,如s t r c p y、s t r c h r和s t r c a t等,只能对A N S I字符串进行操作,不能正确地处理U n i c o d e字符串。因此,ANSI C也拥有一组补充函数。清单2-
25、1显示了一些标准的ANSI C字符串函数,后面是它们的等价U n i c o d e函数。清单2-1 标准的ANSI C字符串函数和它们的等价U n i c o d e函数请注意,所有的U n i c o d e函数均以w c s开头,w c s是宽字符串的英文缩写。若要调用U n i c o d e函数,只需用前缀w c s来取代 A N S I字符串函数的前缀s t r即可。注意大多数软件开发人员可能已经不记得这样一个非常重要的问题了,那就是M i c r o s o f t公司提供的C运行期库与A N S I的标准C运行期库是一致的。ANSI C规定,C运行期库支持U n i c o d
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Windows 核心 编程 002
限制150内