gpt4 book ai didi

windows - 在Win7中,某些字体不能像在Win2K/XP中那样工作

转载 作者:行者123 更新时间:2023-12-02 12:15:25 26 4
gpt4 key购买 nike

我的问题是,如何更改字体处理才能在Windows 7下正常工作。我敢肯定,我已经对以前有效但不再有效的东西做了一个假设。但是我什至不知道从哪里开始寻找!我祈祷有人可以提供帮助!据我了解,以下是详细信息(我也已在Microsoft Windows Developers论坛上发布了此问题,但他们没有回答):

是的,我落后于时代(哎呀,我仍然用纯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_OPAQUE, &r, &ch, 1, NULL )。]请记住,此EXACT代码在Windows 2000,Windows XP和在Windows 7上使用位图字体-但在Windows 7下不能再与固定宽度的True Type字体一起正常使用。

对于任何不了解我需要做什么的人:试想一下,在一张方格纸上每平方写一个字符。每个正方形使用相同的字体,但可能具有不同的前景色和/或背景色。我使用TA_TOP|TA_LEFT文本对齐方式,因为它是最简单的,并且任何持续应用的对齐方式都应适用于固定宽度的字体。

我看到的是ExtTextOut发出的背景矩形比我在RECT *参数中指定的更大。由于我提供的矩形是根据所报告的字体大小创建的,因此永远都不会发生这种情况-在Windows XP和更早的版本中也不会发生这种情况,在Windows 7下使用位图(即.FON)字体也不会发生这种情况。任何一个。但是,在Windows 7下,固定宽度的TrueType字体总是会发生这种情况。这是在Windows 2000,Windows XP和Windows 7(32和64)上运行的EXACT SAME EXECUTABLE。我更倾向于相信我对Windows下的字体处理所做的一些基本假设不再成立(在为Windows编写软件20年之后)。

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

-修订-

对于感兴趣的任何人,我都设法解决了我正在考虑的错误-直到找到相反的文档为止。我的解决方法包括对库的两项更改:

  • 使用从“X”的GetTextExtentPoint32()返回的大小
    来自TEXTMETRICS的数据。
  • 在所有ETO_CLIPPING调用中包括ExtTextOut()标志。

  • 如前所述,以前,我使用 tmHeight+tmExternalLeading来表示文本连续行的顶部之间的像素数。我发现从 GetTextExtentPoint32(返回的size.cy值不一样,而且看起来更准确。我发现的最糟糕的例子是OCRB真型字体。这是我在调试器中看到的针对所创建的OCRB字体的信息(使用系统字体选择对话框):
    ocrbtm.tmHeight          = 11
    ocrbtm.tmExternalLeading = 7

    ocrbsize.cy = 11

    因此,由于某些我尚未发现的原因,Windows忽略了为OCRB字体定义的外部前导值。使用size值而不是TM可以得到美观,整洁,紧凑的文本,这正是我想要的。
    ETO_CLIPPING标志对我来说不是必需的,因为我将矩形设置为单个字符的尺寸,并使用 ETO_OPAQUE填充背景(并覆盖了先前的单元格内容。)但是如果没有裁剪标志,单个字符就是大于大小,文本度量或ABC宽度所表示的宽度-至少,根据到目前为止我发现的所有文档,这都是正确的。

    我相信HEIGHT问题已经存在很长时间了,但是其余的问题是不必要的,直到我们在Windows 7下运行我们的软件。我将其附加到我的问题中,以查看是否有人可以解释我显然不理解的内容。

    -修正案2-

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

    2:在比它应该(通过增加一对额外的像素的权利),但只有当选择了True Type字体Win7的(也许Vista)的 ExtTextOut开始多一点背景填充。即使矩形是字符的预期大小 double (两个尺寸),它也会执行此操作。DPI/缩放可能是一个因素,但是由于我的系统设置为100%,因此Windows似乎在遇到问题1:1的比例因子,这似乎是一个错误。它仅影响真实类型而不影响位图(.FON)字体的事实似乎也排除了缩放(除非 缩放系统中的错误),因为Windows应该尝试缩放所有文本,而不仅仅是缩放某些文本。它的。另外,“自定义DPI设置”对话框中有一个灰色(但已选中)设置“使用Windows XP样式DPI缩放”。最后,整个问题可能是由于我以Windows Classic主题而不是Aero或其他Win7 native 主题之一运行。

    -修正案3-

    简单地调用SetProcessDPIAware()对我遇到的问题没有任何影响。由于我的问题存在于100%DPI设置(比例为1:1)下,如果我的问题 与DPI有关,则我必须在DPI虚拟化中发现一个错误,因为Microsoft就是这样描述该功能的:

    This feature works by providing "virtualized" system metrics and UI elements to the application, as if it were running at 96 DPI. The application then renders to a 96-DPI off-screen surface, and the Desktop Windows Manager scales the resulting application window to match the DPI setting.



    我的所有设置都表明我的缩放比例为100%,而在“自定义设置”框中查看,则可以清楚地看到96 DPI。因此,如果从96 DPI到96 DPI的DPI虚拟化不适用于我的固定宽度的True Type字体,那么Windows会出现问题,对吗?还是有一些我需要调用(或停止调用?)的函数才能使DPI虚拟器正常工作?

    我仍然不相信所谓的缩放问题实际上与我最初认为的SIZE字体有很大关系。这是因为问题表现为背景矩形由ExtTextOut()填充,而不是发出文本字符。当字体为true类型时,背景矩形会放大一点。我现在还验证了是否使用Windows Classic主题或标准Windows Aero主题都会发生此问题。现在构建一个简化的示例,以便其他人可以尝试。

    -修正案4-

    我已经创建了一个最小的演示程序,该程序可以显示我所看到的(以及我在做什么)。Visual Studio 2010项目/源可以从http://www.svalli.com/files/fwtt.7z下载-我故意不包括可执行文件,因为我没有想要冒传播恶意软件的风险。该程序让您选择一种固定宽度的字体,然后将两个5x5字符网格写入客户区,其中一个使用GetTextExtentPoint32大小创建,另一个使用TEXTMETRIC大小创建(如Microsoft所记录)。网格为黑白棋盘格图案,最后在中间写入红色为红色的黄色字符,以显示重叠效果(您可能需要使用zoom实用程序才能清楚地看到它。)该程序还在下面绘制了一个以5 X开头的字符串从相同的左偏移处开始的网格,将用作我放置单个字符(与字符串匹配)的方法的比较。菜单允许切换ExtTextOut中的剪切开/关以及其他字体的选择。还有一个命令行选项dpiaware(区分大小写),它使程序在启动时调用SetProcessDPIAware(),因此也可以评估该调用的效果。

    通过创建此代码,我了解到ExtTextOut正在填充正确的背景矩形,但是使用不透明背景渲染的字符可能比应有的宽度还要宽,甚至可能在ExtTextOut被告知开始绘制的地方甚至无法开始!我说“应该是”是因为我最终得到的字符间距与当我用ExtTextOut渲染整个字符串时得到的字符间距匹配。重叠显然可以在给定矩形的任一侧或两侧,例如,OCRB在字符单元格的左侧和右侧都添加了一个额外的像素,而我检查过的其他真字体在右侧添加了两个像素边缘。

    我确实想以“正确”的方式执行此操作,但是找不到任何文档来表明我做错了或丢失了什么。好吧,我可能会丢失DPI Aware的某些东西,而不是100%的其他东西,但是否则,我感到莫名其妙。

    -修正案5-

    莫名其妙的困惑...问题是由ClearType引起的。关闭ClearType可使所有字体再次工作。在XP下打开ClearType会导致相同的问题。显然,ClearType可以无声地(直到有人告诉我如何检测它)水平地将字符水平拉伸(stretch)几个像素,以便为其添加阴影的像素腾出空间以使其平滑。

    裁剪是解决此问题的唯一方法吗?

    -修正案6-

    上面我的裁剪问题的部分答案:创建新字体时,我现在执行以下操作(使用伪代码):
    CreateFontIndirect
    SelectFont
    GetTextMetrics
    if( (tmPitchAndFamily & TMPF_TRUETYPE) && Win6.x or above )
    if( SystemParametersInfo( SPI_GETCLEARTYPE ) )
    lfQuality = NONANTIALIASED_QUALITY
    DeleteObject( font )
    CreateFontIndirect

    如果没有启用剪切功能,这几乎总是可以使用我使用的字体大小,尽管我发现一些字体仍然在字符单元格的右侧(或左侧)渲染了一个额外的像素。幸运的是,那些字体似乎是在互联网上找到的免费字体,因此它们的总体质量可能低于专业字体类型转换厂的标准。

    如果有人能找到更好的答案,我真的很愿意真的喜欢听到!在那之前,我认为这将是最好的。感谢您阅读本文!

    最佳答案

    确保您的代码是high DPI aware,然后是tell the OS that your process is DPI aware

    如果您不告诉操作系统您知道DPI,则某些测量功能将说谎,并根据显示DPI实际上为96 dpi的假设为您提供数字,而不管其实际值是多少。同时,绘图功能将尝试在另一个方向上缩放。对于简单的高级绘图,此方法通常有效(尽管通常会导致文本模糊)。对于小尺寸测量和单个字符的精确放置,这通常会导致四舍五入的问题,从而导致出现诸如inconsistent font sizes之类的问题。 Windows Vista中引入了此行为。

    您可以在Visual Studio 2010+中始终看到它,因为语法突出显示工具为文本和单词上色,并且在您键入内容时,文本和单词之间会偏移几个像素。真的很烦人。

    关于修订:
    tmExternalLeading只是字体设计者的建议,即关于在文本行之间放置多少额外空间的建议。 MSDN文档通常说:“应用程序在行之间添加的额外前导(空格)量。”好吧,您是应用程序,因此“正确的事情”是在您自己绘制文本时将其添加到行之间,但这实际上取决于您。 (我怀疑像DrawText这样的更高级别的函数会使用它。
    GetTextExtentPoint32(和 friend )返回等于size.cytmHeight并忽略tmExternalLeading是完全正确的。作为程序员,最终选择实际使用多少量最终是您的选择。

    您可以通过一些简单的绘图代码看到这一点。选择tmExternalLeading非零的字体(Arial对我有效)。使用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应用程序。对于此特定字体,这可能不是美学选择。

    关于windows - 在Win7中,某些字体不能像在Win2K/XP中那样工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15091835/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com