I have a custom Label class, drawn text doesn't fits. What am I doing wrong here?
class MyLabel: Label
{
public MyLabel()
{
SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
}
protected override void OnPaint(PaintEventArgs e)
{
using (LinearGradientBrush brush = new LinearGradientBrush(ClientRectangle, Color.Black, Color.LightGray, LinearGradientMode.ForwardDiagonal))
e.Graphics.DrawString(Text, Font, brush, ClientRectangle);
}
}
If I set text of MyLabel to be "123456790 123456790" (AutoSize = true), then I see in Designer (or at run-time) "1234567890 123456789 " (no last zero, but some space). If I try "1234567890 1234567890 1234567890 1234567890", then there will be "1234567890 1234567890 1234567890 12345678 " (no "90", but again some space).
e.Graphics.DrawString(Text, Font, brush, ClientRectangle);
You are using the wrong text rendering method. The Label class auto-sizes itself based on the return value of TextRenderer.MeasureText(). You must therefore use TextRenderer.DrawText() to get the exact same rendered output. You can also set the label's UseCompatibleTextRendering property to true but that should not be your first choice.
Use Graphics.MeasureString to get the required size of the bounding box, then set the size of the label's surface to that size.
Here goes a solution (possible not the best one) to the described problem which can be rephrased as "Autosized Label with Graditent text color".
class MyLabel: Label
{
private bool _autoSize = true;
/// <summary>
/// Get or set auto size
/// </summary>
public new bool AutoSize
{
get { return _autoSize; }
set
{
_autoSize = value;
Invalidate();
}
}
public MyLabel()
{
SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
base.AutoSize = false;
}
protected override void OnPaint(PaintEventArgs e)
{
// auto size
if (_autoSize)
{
SizeF size = e.Graphics.MeasureString(Text, Font);
if (ClientSize.Width < (int)size.Width + 1 || ClientSize.Width > (int)size.Width + 1 ||
ClientSize.Height < (int)size.Height + 1 || ClientSize.Height > (int)size.Height + 1)
{
// need resizing
ClientSize = new Size((int)size.Width + 1, (int)size.Height + 1);
return;
}
}
using (LinearGradientBrush brush = new LinearGradientBrush(ClientRectangle, Color.Black, Color.LightGray, LinearGradientMode.ForwardDiagonal))
e.Graphics.DrawString(Text, Font, brush, ClientRectangle);
}
}
Idea behind is very simple: override AutoSize and process it within Paint event (everything in one place), if required size of text is different from ClientSize - resize control (which will cause redraw). One thing is what you have to add +1 to the width and height because SizeF have fractions and it's better to have +1 pixel more than loose 1 pixel sometimes and have your text not fitting.