Windows 在Win7中,某些字体不';不能像在Win2K/XP中那样工作

Windows 在Win7中,某些字体不';不能像在Win2K/XP中那样工作,windows,fonts,font-size,truetype,Windows,Fonts,Font Size,Truetype,我的问题是如何更改字体处理,以便在Windows7下正常工作。我确信我对一些以前有效但现在不再有效的东西做出了假设。但我甚至不知道从哪里开始找!我祈祷有人能帮忙!以下是我对他们的理解(我也在Microsoft Windows开发者论坛上发布了这个问题,但他们没有回答): 是的,我落后于时代(见鬼,我仍然用纯C编写WIN32代码!)我有一个10年前编写的DLL,它在窗口的客户端区域模仿更旧的DOS屏幕I/O库。不用说,它只允许使用固定宽度的字体。当一些使用DLL的程序被移动到Windows 7时,

我的问题是如何更改字体处理,以便在Windows7下正常工作。我确信我对一些以前有效但现在不再有效的东西做出了假设。但我甚至不知道从哪里开始找!我祈祷有人能帮忙!以下是我对他们的理解(我也在Microsoft Windows开发者论坛上发布了这个问题,但他们没有回答):

是的,我落后于时代(见鬼,我仍然用纯C编写WIN32代码!)我有一个10年前编写的DLL,它在窗口的客户端区域模仿更旧的DOS屏幕I/O库。不用说,它只允许使用固定宽度的字体。当一些使用DLL的程序被移动到Windows 7时,当使用固定宽度的TRUE TYPE字体时会出现奇怪的闪烁(位图字体仍然可以很好地工作)。我们已经跟踪到了这个问题,即使用
ExtTextOut
编写的单个字符比它应该的宽。我用三种不同的方法检查了度量值(对132个字符的字符串使用
GetTextExtentPoint32
除以132,调用
GetTextMetrics
甚至对所有256个字符使用
GetCharABCWidths
),它们都同意字体的宽度相同。但是
ExtTextOut
正在渲染比字体宽度宽一到两个像素的背景矩形。或者它开始在参数中给出的位置左侧渲染一到两个像素的背景[我这样称呼它:
ExtTextOut(hdc,r.left,r.top,ETO_不透明,&r,&ch,1,NULL)
。]记住,这段代码在Windows 2000、Windows XP和,在Windows 7上使用位图字体,但在Windows 7下使用固定宽度的true type字体时,它不再正常工作

对于那些不明白我需要做什么的人:试着想象一下在一张方格纸上写一个字符。每个正方形使用相同的字体,但可能有不同的前景和/或背景色。我使用
TA|u TOP | TA|u LEFT
文本对齐,因为它是最简单的,任何一致应用的对齐方式都应该适用于固定宽度的字体

我看到的是ExtTextOut发出的背景矩形比我在
RECT*
参数中指定的要大。因为我提供的矩形是根据报告的字体大小创建的,所以这种情况永远不会发生——在Windows XP和更早版本上也不会发生,在Windows 7下的位图(即..FON)字体上也不会发生。但在Windows7下,固定宽度的TrueType字体总是会出现这种情况。这与Windows 2000、Windows XP和Windows 7(32&64)上运行的可执行文件完全相同。虽然我想简单地说Windows 7有一个bug,但我更倾向于相信,我对Windows下字体处理所做的一些基本假设不再正确(在为Windows编写软件20年之后)

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

---弹药---

对于任何感兴趣的人来说,我已经设法解决了我所考虑的一个bug——直到我找到了与之相反的文档。我的解决方案包括对我的库的两个更改:

  • 使用从“X”的
    GetTextExtentPoint32()
    返回的大小 来自
    TEXTMETRICS
    的数据量
  • 在所有
    ExtTextOut()
    调用中包括
    ETO\u剪裁
    标志
  • 在此之前,我使用
    tmHeight+tmExternalLeading
    表示连续文本行顶部之间的像素数,如文档所示。我发现从
    GetTextExtentPoint32(
    )返回的size.cy值不一样,似乎更准确。我发现的最糟糕的例子是OCRB true type字体。以下是我在调试程序中看到的我创建的OCRB字体(使用系统字体选择对话框):

    因此,出于我尚未发现的某些原因,Windows忽略了为OCRB字体定义的外部前导值。使用size值而不是TM可以生成漂亮、整洁、紧凑的文本,这正是我想要的

    ETO_CLIPPING
    标志对我来说应该是不必要的,因为我将矩形设置为一个字符的精确尺寸,并使用
    ETO_OPAQUE
    填充背景(并覆盖以前的单元格内容)。但是如果没有剪裁标志,一个字符的宽度将超过大小、文本度量和,或者ABC宽度表示——至少,根据我到目前为止找到的所有文档,这是正确的

    我相信高度问题已经存在很长一段时间了,但是在我们在Windows7下运行我们的软件之前,其余的都是不必要的。我把这个附加在我的问题后面,看看是否有人能解释我显然不懂的东西

    --附件2--

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

    2:在Win7(可能是Vista)下,
    ExtTextOut
    开始填充稍微多一些的背景(通过在右侧添加两个额外的像素),但仅当选择了true type字体时。即使矩形是字符的预期大小(在两个维度上)的两倍,它也会这样做。DPI/缩放可能是一个因素,但由于我的系统设置为100%,Windows似乎在1:1缩放因子方面遇到问题,这似乎是一个错误。它只影响真实类型而不影响位图(.FON)字体这一事实似乎也排除了缩放的可能性(除非存在缺陷)
    ocrbtm.tmHeight          = 11
    ocrbtm.tmExternalLeading =  7
    
    ocrbsize.cy = 11
    
    CreateFontIndirect
    SelectFont
    GetTextMetrics
    if( (tmPitchAndFamily & TMPF_TRUETYPE) && Win6.x or above )
       if( SystemParametersInfo( SPI_GETCLEARTYPE ) )
            lfQuality = NONANTIALIASED_QUALITY
            DeleteObject( font )
            CreateFontIndirect
    
      // 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