正确测量像素中的字符

时间:2012-02-21 06:15:30

标签: c++ clr gdi+ command-line-interface

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

应该提到我正在使用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;
}

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

2 个答案:

答案 0 :(得分:5)

您不应该使用Graphics进行任何文字渲染。

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

  • TextRenderer.MeasureText
  • TextRenderer.DrawText

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

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

注意: GDI +文字呈现由Graphics.DrawStringMeasureString

包裹

以下是GraphicsTextRenderer的衡量结果的比较:

enter image description here

GDI +测量不是“错误”,他们正在做他们想要的事情 - 如果它被渲染为原始文本,则返回文本的大小预期的字体作者(可以使用 Anti-alias rendering 实现):

enter image description here

但是没有人真正希望按照字体设计师的意图来查看文本,因为这会导致内容在像素边界上没有排列 - 使文本太模糊(就像你在苹果电脑)。理想情况下,文本应该在实际像素边界上对齐(即Windows 网格适合

奖金阅读

答案 1 :(得分:2)

MeasureCharacterRanges就像MeasureString一样,但更强大,更准确(也更慢)。