2008-12-23 13 views
37

Me gustaría saber si hay un mejor enfoque para este problema. Quiero cambiar el tamaño de una etiqueta (verticalmente) para acomodar cierta cantidad de texto. Mi etiqueta tiene un ancho fijo (unos 60 caracteres de ancho antes de que deba envolver), unos 495 píxeles. La fuente también tiene un tamaño fijo (12 puntos afaik), pero el texto no.Determinar el tamaño de etiqueta en función de la cantidad de texto y el tamaño de fuente en Winforms/C#

Lo que quiero hacer es aumentar la Altura de etiqueta cuando hay una "Nueva línea" o el texto debe envolver; la idea es que el texto sea completamente visible en la etiqueta. El tamaño automático no funciona porque crecerá en ancho, no en alto.

Por supuesto que podría contar el número de NewLines y agregar: Newlines * LineHeight, y luego-dado que logro poner 60 caracteres por línea, solo divida el número de caracteres y agregue tantos píxeles LineHeight como sea necesario.

Me preguntaba si había una forma más profesional de hacerlo. ¿Mi enfoque es demasiado "cojo"?

Gracias de antemano.

Respuesta

88

¿Qué tal Graphics.MeasureString, con la sobrecarga que acepta una cadena, la fuente y el ancho máximo? Esto devuelve un SizeF, por lo que puede redondear redondear el Height.

 using(Graphics g = CreateGraphics()) { 
      SizeF size = g.MeasureString(text, lbl.Font, 495); 
      lbl.Height = (int) Math.Ceiling(size.Height); 
      lbl.Text = text; 
     } 
+0

+1 de mí, también, pero vamos! Math.Ceiling? Ratón, conoce al obús. :) – MusiGenesis

+0

@MusiGenesis - asegura que redondeamos y no perdemos ningún pixel. Los rounds normales del elenco se redondean hacia abajo, pero sí: podríamos agregar uno para estar seguros ... –

+3

Sé que esto es muy antiguo, y sé que estoy picando, pero este hilo http://stackoverflow.com/ questions/6704923/textrenderer-measuretext-and-graphics-measurestring-mismatch-in-size parece indicar que, en circunstancias normales, TextRenderer.MeasureText proporciona un resultado más preciso que Graphics.MeasureString. – RenniePet

9

Graphics.MeasureString() probablemente lo ayude.

¡Este es también uno de los únicos casos de uso para usar la llamada Control.CreateGraphics()!

+0

¿Cuál es otro caso de uso para CreateGraphics? No puedo pensar en ningún otro. – MusiGenesis

+0

Dije "uno de los únicos" en caso de que haya otro, pero creo que es el único. Para ser sincero, solo estoy repitiendo como loro las preguntas frecuentes sobre GDI de Bob Powell. – Quibblesome

+0

El único otro en el que puedo pensar es para crear gráficos personalizados que desaparecen cuando se arrastra otra ventana sobre ellos, pero eso es más un caso de mal uso. :) – MusiGenesis

33

System.Drawing.Graphics tiene un método MeasureString que se puede utilizar para este propósito. Use la sobrecarga que toma una cadena, una fuente y un parámetro int "ancho"; este último parámetro especifica el ancho máximo permitido para la cadena - use el ancho establecido de su etiqueta para este parámetro.

MeasureString devuelve un objeto SizeF. Use la propiedad Height de este objeto devuelto para establecer la altura de su etiqueta.

Nota: para obtener un objeto Graphics para este fin, puede llamar a esto.CrearGráficos.

0

Bueno, los 60 caracteres pueden ser válidos para el texto de prueba, pero no todos los caracteres tienen el mismo ancho. Por ejemplo, comparar
llllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
y
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

Ambos tienen 60 caracteres, y sin embargo tienen anchuras muy diferentes.

+0

OP dijo que era fuente fija, como servicio de mensajería nuevo. – Quibblesome

+0

De hecho, pero tengo una fuente fija y la cadena de measeura probablemente se encargará de esto. Gracias. –

0

¿Hay algún inconveniente en usar la clase TextRenderer para medir la cadena (como en la respuesta de Marc) en lugar de pasar por el trabajo para crear un objeto de Gráficos, etc.?

+0

TextRenderer es más lento que Graphics.MeasureString. No tengo ni idea de porqué. Sin embargo, ambos son bastante rápidos para la mayoría de los casos de uso. – MusiGenesis

2

Esta "respuesta" es para referencia futura y para combatir la suposición inicial de que AutoSize = true implica que (una etiqueta de WinForms) nunca crecerá en altura.

El siguiente enlace muestra los diversos efectos de AutoSize = verdadero con otras propiedades como MaximumSize. Dependiendo del uso esperado de la pregunta, puede ser apropiado seguir uno de estos enfoques.

http://blogs.msdn.com/jfoscoding/articles/478299.aspx

+1

Cool. Ahora sé por qué todo el código que escribí para cambiar el tamaño de etiquetas como esta nunca funcionó del todo bien. Me gustaría retroceder en el tiempo y abofetearme, pero tendría problemas para elegir una sola fecha a la que regresar. – MusiGenesis

1

he publicado un control de usuario que resuelve este problema en la respuesta aceptada aquí: Autoscale Font in a TextBox Control so that its as big as possible and still fits in text area bounds

El control se extiende RichTextBox. Tiene un método: ScaleFontToFit que cambiará automáticamente el tamaño de la fuente para hacer que todo el texto encaje.

Lo bueno es que respeta la propiedad multiline. Si es cierto, permite que las palabras se envuelvan, de lo contrario no es así.

4
Size maxSize = new Size(495, int.MaxValue); 
_label.Height = TextRenderer.MeasureText(_label.Text , _label.Font, maxSize).Height; 
+1

label.Height = TextRenderer.MeasureText (_label.Text, _label.Font, maxSize, TextFormatFlags.WordBreak) .Height; Incluye "WordBreak" para ajustar el texto y tener una altura esperada. –

0

Según this article se debe utilizar TextRenderer si se va a utilizar un control de Windows Forms para la salida final. TextRenderer y Graphics.MeasureString darán resultados diferentes, por lo tanto, use el que coincida con su modo final de salida.

0

En algunos casos donde debe usar el marco compacto, que no tiene ningún método de anulación para MeasureString(), puede considerar calcular la altura usted mismo.

private int YukseklikAyarla(string p, Font font, int maxWidth) 
    { 
     int iHeight = 0; 
     using (Graphics g = CreateGraphics()) 
     { 
      var sizes = g.MeasureString(p, font); // THE ONLY METHOD WE ARE ALLOWED TO USE 
      iHeight = (int)Math.Round(sizes.Height); 
      var multiplier = (int)Math.Round((double)sizes.Width)/maxWidth; // DIVIDING THE TEXT WIDTH TO SEE HOW MANY LINES IT CAN HAS 
      if (multiplier > 0) 
      { 
       iHeight = (int)(iHeight * (multiplier + 1)); // WE ADD 1 HERE BECAUSE THE TEXT ALREADY HAS A LINE 
      } 
     } 
     return iHeight; 
    } 
Cuestiones relacionadas