正确测量像素中的字符

smo*_*190 1 c++ clr gdi+ command-line-interface

我正在编写一个从头开始的文本框,以便优化语法高亮.但是,我需要以像素为单位获得字符的宽度,而不是像Graphics :: MeasureString给我的垃圾.我在网上发现了很多东西,特别是这个,然而,它似乎都没有用,或者没有考虑到标签.我需要以最快的方式来测量字符的精确尺寸(以像素为单位)和制表符空间.我似乎无法想出这一个......

应该提到我正在使用C++,CLR/CLI和GDI +


这是我的测量功能.在另一个函数中,它返回的RectangleF被绘制到屏幕:

RectangleF TextEditor::MeasureStringWidth(String^ ch, Graphics^ g, int xDistance, int lineYval)
{
    RectangleF measured;
    Font^ currentFont = gcnew Font(m_font, (float)m_fontSize);
    StringFormat^ stringFormat = gcnew StringFormat;
    RectangleF layout = RectangleF(xDistance,lineYval,35,m_fontHeightPix);
    array<CharacterRange>^ charRanges = {CharacterRange(0,1)};
    array<Region^>^ strRegions;

    stringFormat->FormatFlags = StringFormatFlags::DirectionVertical;
    stringFormat->SetMeasurableCharacterRanges(charRanges);

    strRegions = g->MeasureCharacterRanges(ch, currentFont, layout, stringFormat);

    if(strRegions->Length >= 1)
        measured = strRegions[0]->GetBounds(g);
    else
        measured = RectangleF(0,0,0,0);

    return measured;
}
Run Code Online (Sandbox Code Playgroud)

我真的不明白MeasureCharacterRanges layoutRect参数的作用.我修改了Microsofts示例中的代码,仅使用或仅测量一个字符.

Ian*_*oyd 5

您不应该使用Graphics任何文本呈现.

从.NET Framework 2.0开始使用Graphics.MeasureStringGraphics.DrawString不赞成使用新添加的帮助程序类TextRenderer:

  • TextRenderer.MeasureText
  • TextRenderer.DrawText

GDI +文本渲染器已被放弃,10多年来没有任何改进或修复; 以及软件渲染.

GDI渲染(这TextRenderer是一个简单的包装)是硬件加速,并继续得到渲染改进(连字,Uniscribe等).

注意: GDI +文本呈现由Graphics.DrawString和包装MeasureString

下面是测量结果的比较GraphicsTextRenderer:

在此输入图像描述

GDI +测量不是"错误的",它们正在完全按照他们的意图 - 返回文本的大小,如果它被渲染为原始字体作者的意图(可以使用抗锯齿渲染实现):

在此输入图像描述

但是没有人真的按照字体设计者的意图来看待文本,因为这会导致内容在像素边界上没有排列 - 使文本太模糊(就像你在Mac上看到的那样).理想情况下,文本应该在实际像素边界上对齐(即Windows' 网格拟合)

奖金阅读