当前位置:C++技术网 > 资讯 > ETO_GLYPH_INDEX 字样索引表问题

ETO_GLYPH_INDEX 字样索引表问题

更新时间:2017-02-14 20:34:28浏览次数:1+次

当options等于ETO_GLYPH_INDEX时ExtTextOut输入lpString是字样索引表 ,不是文字,在一些网上的资料
http://bbs.csdn.net/topics/390487998,http://www.softwareace.cn/?p=297,
http://blog.csdn.net/norsd/article/details/5304134等都遇到这种情况,我想求教有没有办法通过pString这个字样索引表
获取到对应文字?网上只有转成字样索引表的API,没反API。

C++技术网会员解答:

    你好,先整理一下你的问题。

    在一般情况下,Win32里,我们要输出文字,可以使用TextOut和DrawText就可以了。TextOut和DrawText属于高级函数。我们在使用这两个函数时都可以设置字体。然后就可以输出文字了。而在底层中,我们知道,屏幕中看到的文字等信息都是GDI系统绘制的。TextOut和DrawText作为高级函数,只是提供一些参数,然后让GDI绘制出来。在TextOut和DrawText函数中,我们并没有设置字体等参数,字体等参数是使用单独的API来设置的。也就是说,TextOut和DrawText只是提供文字内容方面的参数设定,字体由字体相关的API函数设定。最终设定好后,在GDI系统中,就将这些参数汇总起来,然后绘制渲染出来。

    所以,TextOut和DrawText只是绘制文字的漫长过程的一个开始而已。当我们设置好字体,填写好要输出的文字之后,就会逐步调用一层层的API函数,其中有一个就是ExtTextOut函数。ExtTextOut函数属于底层函数,所以我们很少接触到,也就对这个机制了解的比较少。

    同样的文字内容,使用不同的字体,最终渲染显示的效果是不一样的。所以,在ExtTextOut函数及更底层的处理过程中,会将文字内容关联到字体系统。字体系统和字符集有点类似,但是不同。字符集是用一个数字来表示的字符,而字体系统则是用一个数字来表示这个字符用这种字体应该长啥样。不过类似之处就在于,字符编码和字体索引都是一个序号,用来确定要使用的那个字最终应该是哪样的。

    字体分为位图字体(用像素点阵形成的图像表示的字符的样子,放大后像素很明显)、矢量字体(通过公式存储,可以无限缩放都清晰)。矢量字体有TrueType字体、PostScript字体和OpenType字体。Windows中使用的是TrueType字体。TrueType字体用数学函数描述字体轮廓外形,含有字形构造、颜色填充、数字描述函数、流程条件控制、栅格处理控制、附加提示控制等指令,所以TrueType字体在显示文字时丰富多彩,效果很好。

    字体决定文字显示的样子,字符集是决定哪些字可以用。一般来说,字体库中的字可以和字符集中的字一一对应,但是也可以只实现一部分常用的字。但是字符集的每一个字符必须要有一个字符编码对应。我们用的最广泛的就是Unicode编码。所以,我们在使用和存储字符时都用字符编码来处理,而显示时,还要将字符编码对应到编码表,取出对应的这个字,同时还要关联到字体库,最终得到要显示的这个字的样子。

    问题提到的是,ExtTextOut使用ETO_GLYPH_INDEX选项时,lpString用的是字体库的索引值,而不是Unicode编码。为了效率考虑,既然字体库的索引可以直接对应字体形状,就不用使用字符编码了。至少在显示绘制时不需要了。所以,我们通过拦截API的形式,拦截到了ExtTextOut函数,得到了lpString的值,结果却是字体库的字样索引值。这样我们就无从得知这个索引值串到底是什么内容了。

    基于上面的分析,我们知道,lpString是索引值串,也就是对应的是字体库的索引值。如果你知道这个字体库的索引表和字符集表的对应关系,也是可以转换得到的。我相信这个是可行的,只是可能会麻烦点。这个资料会比较少。可以尝试一下。

    当然,上面是第一种方案。另外还可以提供一个方案。

    Windows中提供了一套机制,来支持盲人使用Windows,就是我们知道的屏幕阅读器功能。当鼠标停在一个地方的时候,如果那个地方有可读的文字,系统就会提取出界面的信息,进而阅读出来。这个机制也就给我们提供了机会。

    这就是MSAA,UIA ,Windows Automation API。不管是用什么字体显示的,甚至是DirectUI技术绘制的,只要显示在屏幕上,系统都是可以知道的,毕竟都是经过GDI系统来绘制的,系统自然也就能够知道这些内容是什么。只是看系统提供多少接口我们来使用。MSAA,UIA ,Windows Automation API也就是这个提供识别接口的系统。在屏幕取词时,我们可以通过拦截一般的字符编码,也可以拦截使用这种使用了字样索引的形式,而且这也是非常可行的。

    是不是除了上面两个就完了呢?如果你是要识别界面上显示的文字,还可以使用机器视觉来识别文字,在图片转文字功能的实现中,已经很常见了。这些无需借助系统,基于机器视觉和机器学习,来认识字形识别文字,就是手写的不规范的文字也是可以识别出来的。当然这个实现难度会大些,鉴于本问题,就没有必要深究。如果有兴趣,可以学习一下opencv图形库。

    最后,给几个MSAA,UIA ,Windows Automation API和本问题的参考资料:

    1.http://blog.csdn.net/popeer/article/details/6855639

    2.http://shanchunf.blog.163.com/blog/static/1577048020104565759612/

    3.http://stackoverflow.com/questions/21167718/hooking-exttextout-returns-unexpected-results

    4.https://msdn.microsoft.com/en-us/library/windows/desktop/ff486375(v=vs.85).aspx