3

限られたスペースに文字列を描画するために .NET を使用しています。弦はできるだけ太くしたい。文字列がより多くの行に分割されても問題はありません(長方形内にある場合)。問題は、.NET が単語の途中で文字列を別の行に分割することを望まないことです。たとえば、文字列 "Test" は大きなフォントで 1 行に印刷されます。文字列 "Testing" は小さなフォントで 1 行に印刷する必要があり (1 行に "Testi" と別の行に "ng" ではなく)、文字列 "Test Test" はかなり大きなフォントで 2 行に印刷する必要があります。

私の言葉を破らないように .NET を制限する方法について、誰かアイデアがありましたか?

現在、次のようなコードを使用しています。

        internal static void PaintString(string s, int x, int y, int height, int maxwidth, Graphics g, bool underline)
    {
        FontStyle fs = FontStyle.Bold;
        if (underline)
            fs |= FontStyle.Underline;
        Font fnt = new System.Drawing.Font("Arial", 18, fs);
        SizeF size = g.MeasureString(s, fnt, maxwidth);
        while (size.Height > height)
        {
            fnt = new System.Drawing.Font("Arial", fnt.Size - 1, fs);
            size = g.MeasureString(s, fnt, maxwidth);
        }
        y = (int)(y + height / 2 - size.Height / 2);
        g.DrawString(s, fnt, new SolidBrush(Color.Black), new Rectangle(x, y, maxwidth, height));
    }
4

3 に答える 3

2

文字列内で最も長い単語を見つけ、それを使用MeasureStringして 1 行に収まるようにします。

internal static void PaintString(string s, int x, int y, int maxHeight, int maxWidth, Graphics graphics, bool underline)
{
    FontStyle fontStyle = FontStyle.Bold;
    if (underline)
    {
        fontStyle |= FontStyle.Underline;
    }

    var longestWord = Regex.Split(s, @"\s+").OrderByDescending(w => w.Length).First();
    using (var arial = new FontFamily("Arial"))
    using (var format = new StringFormat(StringFormatFlags.LineLimit)) // count only lines that fit fully
    {
        int fontSize = 18;
        while (fontSize > 0)
        {
            var boundingBox = new RectangleF(x, y, maxWidth, maxHeight);
            using (var font = new Font(arial, fontSize, fontStyle))
            {
                int charactersFittedAll, linesFilledAll, charactersFittedLongestWord, linesFilledLongestWord;
                graphics.MeasureString(s, font, boundingBox.Size, format, out charactersFittedAll, out linesFilledAll);
                graphics.MeasureString(longestWord, font, boundingBox.Size, format, out charactersFittedLongestWord, out linesFilledLongestWord);

                // all the characters must fit in the bounding box, and the longest word must fit on a single line
                if (charactersFittedAll == s.Length && linesFilledLongestWord == 1)
                {
                    Console.WriteLine(fontSize);
                    graphics.DrawString(s, font, new SolidBrush(Color.Black), boundingBox, format);
                    return;
                }
            }

            fontSize--;
        }

        throw new InvalidOperationException("Use fewer and/or shorter words");
    }
}
于 2017-10-10T19:43:27.710 に答える
0

文字列の長さ/サイズに応じて、コントロールサイズのサイズを変更できます。これにより、文字列が1行に収まるようになります。

于 2010-03-23T11:23:29.753 に答える
0

あなたがそこに持っているものは正しい答えのようです。フレームワークメソッドへの単一の呼び出しですべてを実行できるとは思いません。ボタンとテキストを winform でレンダリングする場合の別のオプションとして、ButtonRenderer クラスと TextRenderer クラスを確認する必要があります。DrawText または MeasureString を呼び出すときに、WorkBreak、SingleLine、または Ellipse の切り捨てを指定できるようにする TextFormatFlags も指定できます。

于 2010-07-30T04:43:19.913 に答える