System.Drawing.DrawString()长字符串

时间:2017-07-26 20:44:54

标签: c# console-application system.drawing

更新:我想用帮助我解决问题的代码回答我自己的问题。它是由布拉德利提交的,但调整为我工作,也可以帮助其他人。但是在重新开放之前我无法回答。链接的副本提供了一种方法,但没有代码。基于代码的问题答案对社区有用

我在控制台应用程序内部的图像上绘制的文本格式有些轻微问题。我试图绘制的文字是:

  

BAS2016 = PTR = E30BAS2010 =(S20)$ W30 $ PTO2016 = N5W20N5(W20N10)(S10W20)S5W5S5E10N10(E15N5)(S5E15)S10E25 $ W25N10(W15N5)(S5W15)S10W10S15BAS2020 = S15PTO2013 = S5E20S5(E20S10)(N10E20 )N5E5N5W10S10(W15S5)(N5W15)N10W25 $ E25S10(E15S5)(N5E15)N10E10N15W65 $ $ E65N15

我的方法调用是:

RectangleF rectF = new RectangleF(0, 0, 320, 320);

graphics.DrawString(fullTrav, defaultFont, Brushes.Black, rectF);

该输出是:

get

此输出仅适用于Rectangle的默认 StringFormat 。它包装很好,但似乎以不同的方式处理字符并在边框之前推送换行符,具体取决于即将发生的字符。我已经尝试 StringFormatFlag.FitBlackBox 无效,但没有经历过每一面旗帜。

我想得到的是:

want

这个所需的输出看起来更像一个正方形/矩形,并且包含较少的自动换行格式。

有没有办法对Rectangle进行格式化,以便它不会纯粹根据文本命中Rectangle边框时的概念给出字符特殊处理和自动换行?

2 个答案:

答案 0 :(得分:1)

这个小例子(用LINQPad编写)演示了一种方法来包装打破任何字符的文本。您可以根据自己的需要自由定制并改进它(它会泄漏一些资源,并可能会从右侧截断几个像素)。

void Main()
{
    var bmp = new Bitmap(320, 320, PixelFormat.Format32bppArgb);
    using (var g = Graphics.FromImage(bmp))
    {
        g.Clear(Color.Gray);

        var str = @"BAS2016=PTR=E30BAS2010=(S20)$W30$PTO2016=N5W20N5(W20N10)(S10W20)S5W5S5E10N10(E15N5)(S5E15)S10E25$W25N10(W15N5)(S5W15)S10W10S15BAS2020=S15PTO2013=S5E20S5(E20S10)(N10E20)N5E5N5W10S10(W15S5)(N5W15)N10W25$E25S10(E15S5)(N5E15)N10E10N15W65$E65N15$.";
        var font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Regular, GraphicsUnit.Point);           
        int lineIndex=0;
        double lineHeight = font.Height;

        while (str.Length > 0)
        {
            float lineLength = 0;
            int currentChar = 1;

            while (lineLength < bmp.Width - 5 && currentChar <= str.Length)
            {
                string line= str.Substring(0, currentChar);
                lineLength = g.MeasureString(line, font).Width;
                currentChar++;
            }
            g.DrawString(str.Substring(0,currentChar-1),font,Brushes.Black,0,(float)Math.Ceiling(lineIndex*lineHeight),StringFormat.GenericDefault);

            str = str.Substring(currentChar-1);
            lineIndex++;
            currentChar=1;               
        }
    }
    bmp.Dump();
}

它产生以下输出:

Output

答案 1 :(得分:1)

由@BradleyUffner提供的答案。

解决此问题的唯一方法是测量字符串的每个字符,当行长度达到限制时切断行,然后单独打印每行。

代码如下:

using (var graphics = Graphics.FromImage(bmp))
{
    PointF ptF = new PointF(last.textPoints.subCode.X, last.textPoints.subCode.Y + 40);

    int lineIndex = 0;
    double lineHeight = defaultFont.Height;

    while (fullTrav.Length > 0)
    {
        float lineLength = 0;
        int currentChar = 1;
        while (lineLength < 320 && currentChar <= fullTrav.Length)
        {
            string line = fullTrav.Substring(0, currentChar);
            lineLength = graphics.MeasureString(line, defaultFont).Width;
            currentChar++;
        }

        //
        // Optional Code Start
        //
        while (fullTrav[currentChar - 2].ToString().IndexOfAny("(NSEW".ToCharArray()) != -1)
        {
            currentChar--;
        }

        if (currentChar - 1 < fullTrav.Length)
        {
            while (fullTrav[currentChar - 1].ToString().IndexOfAny("1234567890".ToCharArray()) != -1)
            {
                currentChar--;
            }
        }
        //
        // Optional Code End
        //

        graphics.DrawString(fullTrav.Substring(0, currentChar - 1), defaultFont, Brushes.Black, ptF.X, ptF.Y + lineIndex * 20, StringFormat.GenericDefault);

        fullTrav = fullTrav.Substring(currentChar - 1);
        lineIndex++;
        currentChar = 1;

    }
}

此代码包含和我以前仅在特定字符上打破的可选区域。为了解释一下,它可以防止它分裂&#34; N4&#34;或&#34; W17&#34;在两个不同的行之间它会阻止一个开头的括号&#34;(&#34;来自一行中的最后一个字符。

成品看起来像:

solved