I know I shouldn't be using a textbox for this, but I was writing it just for testing purposes for the logic to be implemented into a custom control that has been made.
Anyways, I was trying to get the drawn string to auto-size itself (both font size and word wrapping). I have noticed that the font size will sometimes be off by 1 each time. I set a button that toggles the textbox's .AutoFit (New control inheriting Textbox). IE: First press would set fontsize at 15 and look perfect. Second press disables AutoFit and text is drawn normally. Third press re-enables AutoFit, but fontsize would be 16 now. Next time, back to 15, and it keeps going...
Any ideas what I might be doing wrong?
Anyways, I was trying to get the drawn string to auto-size itself (both font size and word wrapping). I have noticed that the font size will sometimes be off by 1 each time. I set a button that toggles the textbox's .AutoFit (New control inheriting Textbox). IE: First press would set fontsize at 15 and look perfect. Second press disables AutoFit and text is drawn normally. Third press re-enables AutoFit, but fontsize would be 16 now. Next time, back to 15, and it keeps going...
Any ideas what I might be doing wrong?
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace test
{
public partial class Form1 : Form
{
AutoFitTextBox atf;
string shortstr = "Short string";
string longstr = "This is a really really long text string which needs to be word wrapped. Let's just see how long we can make this string while knowing that it must become wrapped at some point. And now to end this string of long text.";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if(atf.AutoFit)
atf.AutoFit = false;
else
atf.AutoFit= true;
atf.Invalidate();
}
private void Form1_Load(object sender, EventArgs e)
{
atf = new AutoFitTextBox();
atf.Multiline = true;
atf.ReadOnly = true;
atf.Enabled = false;
atf.WordWrap = false;
atf.Location = textBox1.Location;
atf.Size = textBox1.Size;
atf.Text = longstr;
atf.Visible = true;
Controls.Add(atf);
}
}
public class AutoFitTextBox : TextBox
{
private int _autofitfontsize;
public AutoFitTextBox()
{
this.SetStyle(ControlStyles.UserPaint, true);
_autofitfontsize = (int)this.Font.Size;
}
public bool AutoFit { get; set; }
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//string txt;
if (AutoFit)
{
//test wordwrapping
//txt = Wrap(e.Graphics, this.Text);
_autofitfontsize = autoFit(e.Graphics, this.Text);
e.Graphics.DrawString(Wrap(e.Graphics,this.Text), new Font(this.Font.Name,(float)_autofitfontsize), Brushes.Black, 0,0);
//e.Graphics.DrawString(autoFit(e.Graphics, this.Text), this.Font, Brushes.Black, 0, 0);
}
else
e.Graphics.DrawString(this.Text, this.Font, Brushes.Black, 0,0);
}
private int autoFit(Graphics g, string str)
{
//if needing to wrap
if (Wrap(g, str).Contains("\n"))
{
if ((int)g.MeasureString(Wrap(g, str), new Font(this.Font.Name, (float)_autofitfontsize)).Height > this.Height)
{
while ((int)g.MeasureString(Wrap(g, str), new Font(this.Font.Name, (float)_autofitfontsize)).Height > this.Height)
{
int test = (int)g.MeasureString(Wrap(g, str), new Font(this.Font.Name, (float)_autofitfontsize)).Height;
//decrease font size by 1 and try wrapping again
_autofitfontsize -= 1;
}
}
else if ((int)g.MeasureString(Wrap(g, str), new Font(this.Font.Name, (float)_autofitfontsize)).Height < this.Height) //check for being below height to try increasing accordingly
{
while ((int)g.MeasureString(Wrap(g, str), new Font(this.Font.Name, (float)_autofitfontsize)).Height < this.Height)
{
int test = (int)g.MeasureString(Wrap(g, str), new Font(this.Font.Name, (float)(_autofitfontsize+1))).Height;
if ((int)g.MeasureString(Wrap(g, str), new Font(this.Font.Name, (float)(_autofitfontsize+1))).Height > this.Height)
break;
_autofitfontsize += 1;
}
}
}
else
{
//increase font size enough to cover width
}
return _autofitfontsize;
}
private string Wrap(Graphics g, string str)
{
string newstring = "";
List<string> newstrings = new List<string>();
char[] chr = "\n".ToCharArray();
newstrings.AddRange(str.Split(' '));
string teststring = "";
bool last=false;
//pile on 1 word at a time until > width
for (int i = 0; i < newstrings.Count; i++)
{
while ((int)g.MeasureString(teststring, new Font(this.Font.Name,(float)_autofitfontsize)).Width < this.Width)
{
//int test = (int)g.MeasureString(teststring, this.Font).Width;
//addingto = str.Substring(0, str.IndexOf(" "));
//str = str.Remove(0, str.IndexOf(" ") + 1);
teststring += newstrings[i] + " ";
i++;
if (i == newstrings.Count)
{
last = true;
break;
}
}
//if we get here, teststring is too long, remove last word
if (!last)
{
string addingto = teststring.Substring(0, teststring.LastIndexOf(" ")) + "\n";
if (addingto.Contains(" "))
{
newstring += addingto.Substring(0, addingto.LastIndexOf(" ")) + "\n";
i -= 2;
}
else
{
newstring += addingto;
i--;
}
}
else
{
newstring += teststring;
break;
}
teststring = "";
//i-=2;
//str = addingto + " " + str;
}
return newstring;
}
}
}