I am using .NET to draw a string into a limited space. I want the string to be as big as possible. I have no problem in the string breaking up into more lines (if it stays inside the rectangle). Now the problem: I don't want .NET to break the string in different lines in the middle of a word. For example string "Test" prints on a single line in a big font. String "Testing" should print on a single line in a smaller font (and not "Testi" on one line and "ng" on another) and string "Test Test" should print on two lines in a fairly large font.
Anybody got ideas on how to restrict .NET not to break my words?
I'm currently using a code like this:
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));
}
Find the longest word in your string and use MeasureString
to ensure it fits on one line:
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");
}
}
You could resize the control size depending upon the length/size of the string. This would make sure that the string fits in one line.
What you have got there seems to be the right answer. I dont think there is a single call to the framework method that can do all that for you. Another option if you are rending button and text in winform, you should look at the ButtonRenderer and TextRenderer class. When calling DrawText or MeasureString you can also specify TextFormatFlags which will allow you to specify WorkBreak, SingleLine or using Ellipse truncation.
来源:https://stackoverflow.com/questions/2499067/disable-word-breaking-when-wrapping-lines-in-net-drawstring