c# - resolucion - Control de usuario con propiedad de altura automática
obtener resolucion de pantalla c# (1)
Quiero crear un control de usuario que muestre el texto.
Necesito una forma de cambiar el tamaño del control en tiempo de ejecución para que ajuste la altura para mostrar todo el texto. Creé un control que se ve así:
Como puede ver, tengo el icono y el texto dibujados con TextRenderer.DrawText
. Lamentablemente, cuando cambio el tamaño de mi control (solo a la izquierda o a la derecha) mi texto a veces se corta, asno se muestra a continuación:
Estoy midiendo texto usando TextRenderer.MeasureText
basado en que estoy contando el número de líneas y luego estoy dibujando ese texto. Aquí está el código que estoy usando:
[Designer(typeof(MyTextBoxDesigner))]
public partial class MyTextBox : UserControl
{
public MyTextBox()
{
InitializeComponent();
}
[DefaultValue("Demo"), Description("Text of control"), Category("Appearance"),Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override string Text
{
get
{
return base.Text;
}
set
{
if (base.Text == value) return;
base.Text = value;
Invalidate();
}
}
Image _image;
[Description("Image shown on the left side of the control"),
Category("Appearance")]
public Image Image
{
get
{
return _image;
}
set
{
if (_image == value) return;
_image = value;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
int imagePadding = 0;
if (_image != null)
{
imagePadding = 25;
e.Graphics.DrawImage(_image,new Rectangle(5,5,16,16));
}
Size textSize1 = TextRenderer.MeasureText(e.Graphics, Text, Font);
SizeF textSize2 = e.Graphics.MeasureString(Text, Font);
Debug.WriteLine(textSize2);
int maxTextWidth = Width - Padding.Left-Padding.Right-imagePadding;
int lineHeight = textSize1.Height + 2;
int numLines = 1;
if (textSize1.Width > maxTextWidth)
{
numLines = textSize1.Width / maxTextWidth + 1;
}
Rectangle textRect = new Rectangle
{
Width = Width - Padding.Left-Padding.Right-imagePadding,
Height = (numLines * lineHeight),
X = Padding.Left+imagePadding,
Y = 5
};
TextRenderer.DrawText(e.Graphics, Text, Font, textRect, ForeColor, TextFormatFlags.WordBreak | TextFormatFlags.Left | TextFormatFlags.Top);
e.Graphics.DrawRectangle(Pens.CadetBlue, textRect);
base.OnPaint(e);
}
}
internal class MyTextBoxDesigner : ControlDesigner
{
public override SelectionRules SelectionRules
{
get
{
//all minus bottom and top
return (base.SelectionRules & ~(SelectionRules.BottomSizeable | SelectionRules.TopSizeable));
}
}
}
Idealmente, me gustaría que mi control autoajuste la altura según la longitud del texto, por lo que si el texto es corto (o el tiempo suficiente), por ejemplo, 20px de altura, pero si el texto es largo, mi control debería ser (por ejemplo) 40px altura (2 líneas de texto).
¿Cómo debo cambiar mi medición de texto para calcular el textRect
correctamente?
¿Debo actualizar la altura de mi control usando la propiedad Tamaño o hay una forma mejor?
EDITAR: Básicamente quiero dibujar texto que pueda envolver dentro de un rectángulo, pero que tenga un ancho fijo, de modo que cuando el texto sea más largo, ese rectángulo ajustará su altura. Luego, en función de esa altura, quiero ajustar la altura de control.
Aquí hay un control automático de altura. Si cambia el ancho del control, la altura del control cambiará de manera que se pueda mostrar todo el texto.
Puede crear dicho control utilizando diferentes enfoques que incluyen:
Método 1: Control compuesto de tamaño automático que aloja una etiqueta
Este enfoque se basa en alojar unaLabel
tamaño automático con ancho máximo dinámico en unControl
tamaño automático. En este enfoque, establecemos el ancho máximo de etiqueta según el ancho de control y, dado que la etiqueta es de tamaño automático, su altura se configurará automáticamente para mostrar todos los textos y luego estableceremos la altura del control en función de la altura de la etiqueta.Enfoque 2: control simple de tamaño automático desde cero sin etiqueta
Este enfoque se basa en anularSetBoundsCore
y establecer el tamaño de control en función de su tamaño deText
. En este enfoque calculamos el tamaño del texto en función del ancho de control utilizandoTextRenderer.MeasureText
y luego establecemos la altura calculada como la altura del control. En este enfoque, debe manejar los indicadores de formato de texto y representarse usted mismo.
En ambos enfoques, un ControlDesigner
se usa para deshabilitar todos los ControlDesigner
tamaño, excepto izquierdo y derecho.
tenga en cuenta
Estos no son los únicos enfoques disponibles, pero son buenos ejemplos. Como otra opción, puede heredar de una Label
y cambiar su comportamiento.
Método 1: Control compuesto de tamaño automático que aloja una etiqueta
Funciona sobre la base de establecer la propiedad AutoSize
de label en true
y luego establecer MaximumSize
de label en función del Width
contol. También la altura del control se establece en función de la altura de la etiqueta. Simplemente puede dibujar la imagen en el método OnPaint
. También puede agregar un PictureBox
para la imagen.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
[Designer(typeof(MyLabelDesigner))]
public partial class MyLabel : Control
{
public MyLabel() { InitializeComponent(); }
private System.Windows.Forms.Label textLabel;
private void InitializeComponent()
{
this.textLabel = new System.Windows.Forms.Label();
this.textLabel.AutoSize = true;
this.textLabel.Location = new System.Drawing.Point(0, 0);
this.textLabel.Name = "label1";
textLabel.SizeChanged += new EventHandler(textLabel_SizeChanged);
this.AutoSize = true;
this.Controls.Add(this.textLabel);
}
void textLabel_SizeChanged(object sender, EventArgs e)
{
this.Height = this.textLabel.Bottom + 0;
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.textLabel.MaximumSize = new Size(this.Width, 0);
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override string Text
{
get { return this.textLabel.Text; }
set { this.textLabel.Text = value; }
}
}
Enfoque 2: control simple de tamaño automático desde cero sin etiqueta
Este enfoque funciona según el tamaño de control establecido en SetBoundsCore
en función del ancho actual y la altura calculada de su Text
. Para calcular la altura del control. Simplemente puede dibujar la Image
.
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms.Design;
[Designer(typeof(MyLabelDesigner))]
public class ExLabel : Control
{
public ExLabel()
{
AutoSize = true;
DoubleBuffered = true;
SetStyle(ControlStyles.ResizeRedraw, true);
}
protected override void OnTextChanged(System.EventArgs e)
{
base.OnTextChanged(e);
SetBoundsCore(Left, Top, Width, Height, BoundsSpecified.Size);
Invalidate();
}
protected override void SetBoundsCore(int x, int y, int width, int height,
BoundsSpecified specified)
{
var flags = TextFormatFlags.Left | TextFormatFlags.WordBreak;
var proposedSize = new Size(width, int.MaxValue);
var size = TextRenderer.MeasureText(Text, Font, proposedSize, flags);
height = size.Height;
base.SetBoundsCore(x, y, width, height, specified);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
var flags = TextFormatFlags.Left | TextFormatFlags.WordBreak;
TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle,
ForeColor, BackColor, flags);
}
}
Diseñador
Aquí está el ControlDesigner
que solía limitar los manejadores de agarre de tamaño en el diseñador hacia la izquierda y hacia la derecha para ambas implementaciones:
using System.Windows.Forms.Design;
public class MyLabelDesigner : ControlDesigner
{
public override SelectionRules SelectionRules
{
get
{
return (base.SelectionRules & ~(SelectionRules.BottomSizeable |
SelectionRules.TopSizeable));
}
}
}