在Win7的某些字体不工作就像他们在Win2K / XP做(In Win7 some fonts d

2019-08-17 04:07发布

我的问题是关于需要多字体的处理被改变,以在Windows 7正常工作我敢肯定,我做的东西,以前是有效的假设,但不再有效。 但是,我甚至不知道从哪里开始找! 我祈祷有人能够帮助! 下面是详细信息我了解他们(我也张贴在Microsoft Windows开发者论坛这个问题,但他们没有回答):

是的,我的时间(赫克,我还是写在普通的C代码WIN32!)我有一个10岁的老DLL我写后面,模仿一个窗口的工作区域内的更老的DOS屏幕I / O库。 不用说,它只是允许使用的固定宽度字体。 当一些使用DLL的程序已经被移动到Windows 7,还有当使用固定宽度的True Type字体出现一个奇怪的闪烁(位图字体仍正常工作。)我们已经跟踪这个问题到事实与写入单个字符ExtTextOut宽度大于它应该是。 我检查测量三种不同的方法(通过使用GetTextExtentPoint32在132字符串和132分,通过调用GetTextMetrics ,即使只使用GetCharABCWidths所有256个字符),他们都同意,字体是相同的宽度。 但ExtTextOut正在呈现矩形背景比字体宽度较宽的一个或两个像素。 任一比,或它开始后台生成一两个像素在参数[I这样称呼它给出的位置的左侧: ExtTextOut( hdc, r.left, r.top, ETO_OPAQUE, &r, &ch, 1, NULL ) 。]请记住,这个确切的代码工作完全的Windows 2000,Windows XP中,并与位图字体的Windows 7 -但它不再与固定宽度True Type字体正常工作在Windows 7下。

对于任何人谁不抓什么,我需要做的:试着想象在一张方格纸书写每平方一个字符。 每平方使用相同的字体,但可以具有不同的前景和/或背景色。 我用TA_TOP|TA_LEFT文本对齐方式,因为它是最简单,任何持续应用走线应为固定宽度字体工作。

我所看到的是,ExtTextOut被发射,比我在已经指定了较大的背景矩形RECT *参数。 由于我提供的矩形从字体的报告的大小创建的,这是不可能发生的 - 它从来没有发生在Windows XP和更早版本,并且不与位图发生(即.FON)在Windows 7下字体,无论是。 但它总是在Windows 7下的固定宽度的TrueType字体发生这与Windows 2000上运行完全相同的可执行文件,Windows XP和Windows 7(32和64),虽然我很想简单地说Windows 7有一个bug,我更倾向于认为,我做了有关Windows下的字体处理一些基本的假设不再是真实的(20年后为Windows编写的软件。)

但我不知道如何或在哪里发现了什么,可能是! 请,请帮帮我!

--- ammendment ---

任何有兴趣,我已经成功地解决我所考虑的一个错误 - 直到我找到文档相反。 我的解决方法包括两个更改我的图书馆:

  1. 使用来自返回的大小GetTextExtentPoint32()一个“X”,而不是从数据的TEXTMETRICS
  2. 包括ETO_CLIPPING所有标志ExtTextOut()调用。

以前,我是用tmHeight+tmExternalLeading文本的连续行的顶部之间的像素数,如记录。 我发现size.cy值来从后面GetTextExtentPoint32(是不一样的,而且似乎更准确。 我发现最糟糕的例子是OCRB True Type字体。 下面是我在调试器的OCRB字体我会创造看到(使用系统字体选择对话框):

ocrbtm.tmHeight          = 11
ocrbtm.tmExternalLeading =  7

ocrbsize.cy = 11

因此,对于某些原因,我还没有发现,Windows正在忽略了OCRB字体定义的外部引导值。 使用大小值,而不是TM导致美观大方,整齐,紧密堆积的文本,这正是我想要的。

ETO_CLIPPING因为我设置了矩形单个字符的准确尺寸和标志使用应该没有必要对我ETO_OPAQUE填写背景(并覆盖前一个单元格的内容)。但是,如果没有裁剪标志,单个字符比任何大小,文本度量或ABC宽度更宽将表明 - 至少,基于所有我到目前为止发现的文件是真的。

我相信,身高问题已经存在了很长一段时间,但休息是不必要的,直到我们的Windows 7下运行我们的软件,我这个追加我的问题,看看是否有人能解释一下我显然不明白。

- ammendment 2 -

1:所有的文档,我能找到说tmHeight+tmExternalLeading应该产生文本的单行距。 期。 但是,这并非总是如此,我无法找到文件说明Windows如何确定有时是由返回不同的值GetTextExtentPoint32()

2:win7下(也许Vista)的ExtTextOut开始多一点背景填充比它应该(通过增加一对额外的像素的权利),但只有当选择了True Type字体。 它这样做,即使矩形是双重性格的预期大小(在这两个方面。)DPI /缩放可能是一个因素,但因为我的系统设置为100%,这似乎Windows已具有与1麻烦:1比例因子和这似乎是一个错误。 它不仅影响真正的类型,而不是位图的事实(.FON)字体也似乎排除缩放( 除非在缩放系统中的错误),因为Windows应尝试扩展所有的文字,不只是它的一些。 此外,还有一个灰色的(但检查)设置“使用Windows XP样式DPI缩放”,在“自定义DPI设置”对话框。 最后,这整个问题可能是我下的Windows经典主题运行,而不是航空或其他Win7本土主题之一的结果。

- ammendment 3 -

简单地调用SetProcessDPIAware()目前在我遇到的问题没有影响。 由于我的问题在100%的DPI设置存在(比例为1:1),如果我的问题 DPI相关的,那么我一定是发现了DPI虚拟化的一个错误,因为这是微软是如何描述的特征:

这个功能是通过提供“虚拟化”系统度量和UI元素的应用,就好像它是在96 DPI运行。 然后,应用程序呈现到96 DPI离屏表面,并且所述桌面窗口管理器缩放生成的应用程序窗口,以匹配DPI设置。

我所有的设置表明我在100%缩放,并期待在自定义设置框清楚地表明,这意味着96 DPI。 所以,如果从96 DPI DPI的虚拟化96 DPI不工作对我的固定宽度的True Type字体,那么Windows有问题,对不对? 或者是有一些功能我需要调用(或停止打电话?)为了让DPI虚拟器才能正常工作?

我仍然不相信,认为规模问题实际上有尽可能多的做的字体大小,因为我原本以为。 这是因为这个问题在后台矩形通过充满表现ExtTextOut()而不是文本字符被发射。 背景矩形被放大的位时的字体是真实类型。 我现在也证实是否发生使用Windows经典主题或标准的Windows Aero主题这个问题。 现在建立一个简单的例子,以便其他人可以用它进行试验。

- ammendment 4 -

我创建了一个最小的演示程序,显示我看到什么(我在做什么。)在Visual Studio 2010中的项目/来源可以从以下网址下载http://www.svalli.com/files/fwtt.7z - 我有意没有可执行文件,因为我不想冒险传播的恶意软件。 该方案有你选择一个固定宽度字体,然后输出两种5x5的字符网格客户区,一个使用创建GetTextExtentPoint32大小和一个使用TEXTMETRIC大小按照Microsoft的说明。 该网格是在去年写进中心显示重叠效果的红色字符黄色黑白方格图案(可能需要缩放工具清楚地看到它。)该方案还利用与5 X的正下方开头的字符串网格,开始以相同的左偏移,以被用作用于我的放置单个字符的方法的比较(I字符串匹配。)菜单允许切换限幅的开/关在ExtTextOut等字体的选择。 还有一个命令行选项dpiaware (区分大小写)导致程序调用SetProcessDPIAware()启动时,使得该呼叫的效果也可以评估。

从创建这个我明白了, ExtTextOut是填补了正确的矩形背景,但人物被用不透明的背景上呈现可以更宽比它应该是,不得甚至开始在那里ExtTextOut被告知要开始画! 我说:“应该是”,因为字符间距,我结束了比赛我所得到的,当我有ExtTextOut渲染整个字符串。 重叠可显然是在任或指定的矩形两侧,例如,OCRB增加了额外的像素到两个字符单元的左边和右边,而我已经检查了其他True Type字体添加两个像素的权利边缘。

我真的想这样做“正确”的方式,但我无法找到任何文件,证明我在做什么错误或很想念。 好吧,我可能失去了一些东西的DPI在100%以外秤意识到,但除此之外,我只是百思不得其解。

- ammendment 5 -

略显不足百思不得其解......问题是由的ClearType引起的。 关闭ClearType的取得所有的字体的再次合作。 接通XP下的ClearType导致同样的问题。 显然的ClearType可以默默水平,以腾出空间为它添加到事情顺利的阴影像素(直到有人告诉我如何检测它)长字符的像素夫妇。

削波解决这个问题的唯一途径?

- ammendment 6 -

部分回答了我的问题裁剪上面:当创建一个新的字体我现在做的(伪代码)以下内容:

CreateFontIndirect
SelectFont
GetTextMetrics
if( (tmPitchAndFamily & TMPF_TRUETYPE) && Win6.x or above )
   if( SystemParametersInfo( SPI_GETCLEARTYPE ) )
        lfQuality = NONANTIALIASED_QUALITY
        DeleteObject( font )
        CreateFontIndirect

如果没有启用这个剪裁几乎总是与我使用的字体大小的作品,但我已经找到了几个仍然呈现一个额外的像素字符细胞的右(或左)。 幸运的是,这些似乎是在互联网上找到免费字体,所以他们的整体素质可能是下面的专业代工厂字体的标准。

如果任何人都可以找到一个更好的答案,我真的, 真的喜欢听! 在那之前,我认为这是好,因为它会得到。 感谢远阅读本!

Answer 1:

确保你的代码是高DPI知道 ,然后告诉OS,你的过程是DPI感知 。

如果你不告诉你是DPI感知操作系统,一些测量功能会撒谎,让你基于这样的假设数字,显示DPI实际上是不管它到底是什么96 dpi的。 同时,绘图函数将尝试扩大在其他方向。 对于简单的高级绘图,这种方法通常工作(尽管它往往会导致模糊文本)。 对于小型测量和单个字符的精确位置,这常常导致四舍五入导致之类的问题不一致的字体大小 。 这种行为在Windows Vista中引入。

你可以看到这一切在Visual Studio 2010+的时间为语法高亮颜色的文本和单词的像素夫妇在键入时移在这里和那里。 真的frickin'烦人。

关于修订:

tmExternalLeading是简单地从字体设计,以多少额外的空间文本行之间放一个建议。 MSDN文档通常说,“额外领先(空间)量,应用排之间增加了。” 嗯,你的应用程序,因此,“正确的事情”,是行间添加它,当你自己绘制文本,但它确实是由你。 (我怀疑像DrawText的更高级别的功能,将使用它。

这是完全正确的GetTextExtentPoint32 (朋友)返回一个size.cy等于tmHeight ,而忽略tmExternalLeading 。 作为程序员,这是最终你选择多少导致实际使用。

你可以看到,这与一些简单的绘制代码。 选择具有非零tmExternalLeading(宋体对我的作品)的字体。 绘制使用一些文本TextOut和独特的背景色。 然后测量与文本GetTextExtentPoint32并绘制根据你拿回值一些行。 你会看到,背景色的矩形排除外部领先。 外部的引导就是:外部。 这不是在字符单元的边界。

  // Draw the sample text with an opaque background.
  assert(::GetMapMode(ps.hdc) == MM_TEXT);
  assert(::GetBkMode(ps.hdc) == OPAQUE);
  assert(::GetTextAlign(ps.hdc) == TA_TOP);
  COLORREF rgbOld = ::SetBkColor(ps.hdc, RGB(0xC0, 0xFF, 0xC0));
  ::TextOutW(ps.hdc, x, y, pszText, cchText);
  ::SetBkColor(ps.hdc, rgbOld);

  // This vertical line at the right side of the text shows that opaque
  // background is exactly the height returned by GetTextExtentPoint32.
  SIZE size = {0};
  if (::GetTextExtentPoint32W(ps.hdc, pszText, cchText, &size)) {
    ::MoveToEx(ps.hdc, x + size.cx, y, NULL);
    ::LineTo(ps.hdc, x + size.cx, y + size.cy);
  }

  // These horizontal lines show the normal line spacing, taking into
  // account tmExternalLeading.
  assert(tm.tmExternalLeading > 0);  // ensure it's an interesting case
  ::MoveToEx(ps.hdc, x, y, NULL);
  ::LineTo(ps.hdc, x + size.cx, y);  // top of this line
  const int yNext = y + tm.tmHeight + tm.tmExternalLeading;
  ::MoveToEx(ps.hdc, x, yNext, NULL);
  ::LineTo(ps.hdc, x + size.cx, yNext);  // top of next line

彩色矩形的底部和下一行的顶部之间的间隙表示外部引出,这始终是字符单元的外部。

OCR-B是专为银行设备可靠的光学字符识别。 有一个大的外部领导(相对于实际文本的高度)可能适合一些OCR应用程序。 对于这个特殊的字体,这可能不是一个审美的选择。



文章来源: In Win7 some fonts don't work like they did in Win2K/XP