C# 如何精确测量字符宽度?

C# 如何精确测量字符宽度?,c#,.net,width,character,C#,.net,Width,Character,也许我有点不对劲,但是。。。我想模拟字符间距。 我将单词(文本)分解成单个字符的列表,测量它们的宽度,然后在位图上一个接一个地绘制它们。我想,渲染文本的总宽度将与整个未拆分字符串的宽度相同,但存在一些问题。在循环中渲染字符显示更广泛的结果。有什么方法可以得到共同的(预期的)结果吗 以下是一段代码片段: private struct CharWidths { public char Char; public float Width; } private List<CharW

也许我有点不对劲,但是。。。我想模拟字符间距。 我将单词(文本)分解成单个字符的列表,测量它们的宽度,然后在位图上一个接一个地绘制它们。我想,渲染文本的总宽度将与整个未拆分字符串的宽度相同,但存在一些问题。在循环中渲染字符显示更广泛的结果。有什么方法可以得到共同的(预期的)结果吗

以下是一段代码片段:

private struct CharWidths
{
    public char Char;
    public float Width;
}

private List<CharWidths> CharacterWidths = new List<CharWidths>();
私有结构字符宽度
{
公共字符;
公共浮动宽度;
}
私有列表字符宽度=新列表();

private void GetCharacterWidths(字符串文本、位图BMP)
{
int i;
int l=文本长度;
CharacterWidths.Clear();
Graphics g=Graphics.FromImage(BMP);
CharWidths cw=新的CharWidths();
对于(i=0;i

public void渲染位图(位图BMP)
{
//MessageBox.Show(“颜色”);
Graphics g=Graphics.FromImage(BMP);
GetCharacterWidths(“Lyborko”,BMP);
int i;
浮动X=0;
PointF P=新的PointF();
对于(i=0;i

Thanx很多

首先应该说,没有解决这个问题的灵丹妙药,但有一些关于这个问题的建议:

  • 考虑到您通过调用
    TextRenderer.MeasureText
    不会传递当前
    设备上下文
    (与您在后面绘制字符串时使用的上下文相同)知道了一个简单的事实,
    MeasureText
    仅在缺少该参数的情况下创建一个与桌面兼容的新参数,并调用
    DrawTextEx
    windowsdk函数,我想说,首先在指定的地方使用重载,比如第一个参数
    设备上下文
    ,然后用它来呈现文本。可能会有所不同

  • 如果失败,我将尝试使用该方法来猜测屏幕上控件的最大可能呈现尺寸,因此实际上是您未来字符串位图的尺寸。要做到这一点,您可以创建一些临时控件,分配一个字符串,渲染并在调用此函数后执行。我很清楚,这个解决方案可能很难适合您的应用程序架构,但可能会产生更好的结果


  • 希望这能有所帮助。

    一旦你遇到了“不寻常”的角色,你的方法就注定要失败。例如,存在组合字符,其中多个代码点在屏幕上呈现为单个符号。您的代码还将文本拆分为UTF-16代码单位,而不是代码点。@CodeInChaos Ok,这肯定不是最好的,但我应该怎么做?这个问题很好地说明了为什么这样做不起作用:测量字符串,而不是字符。我试着按照您的建议指定DeviceContext:Size textSize=TextRenderer.MeasureText(g,text[I].ToString(),Font);但是没有发生变化…@lyborko:那么第二种选择呢?第二种选择我没有试过。通过设置TextFlags,我获得了显著的效果,但差异仍然是可见的(尽管是像素)。请参阅:TextFormatFlags flags=TextFormatFlags.noppadding;尺寸si=新尺寸(1,1);Size textSize=TextRenderer.MeasureText(g,Text[i].ToString(),Font,si,flags);
    private void GetCharacterWidths(string Text, Bitmap BMP)
    {
        int i;
        int l = Text.Length;
        CharacterWidths.Clear();
        Graphics g = Graphics.FromImage(BMP);
    
        CharWidths cw = new CharWidths();
        for (i = 0; i < l; i++)
        {
            Size textSize = TextRenderer.MeasureText(Text[i].ToString(), Font);
            cw.Char = Text[i];
            cw.Width = textSize.Width;
            CharacterWidths.Add(cw);
        }
    }
    
    public void RenderToBitmap(Bitmap BMP)
    {
        //MessageBox.Show("color");
    
        Graphics g = Graphics.FromImage(BMP);
        GetCharacterWidths("Lyborko", BMP);
    
        int i;
        float X = 0;
        PointF P = new PointF(); 
        for (i = 0; i < CharacterWidths.Count; i++)
        {
            P.X = X;
            P.Y = 0;
    
            g.DrawString(CharacterWidths[i].Char.ToString(), Font, Brushes.White, P);
    
            X = X+CharacterWidths[i].Width;
        }
    
        P.X = 0;
        P.Y = 30;
        g.DrawString("Lyborko", Font, Brushes.White, P);
        // see the difference
    }