2009-08-05 46 views
12

A veces los mensajes de excepción de Microsoft son exasperantemente inútiles. He creado un pequeño y agradable método MVC para renderizar texto. El cuerpo del método está abajo. Cuando llega al método "DrawString", aparece una excepción que dice "El parámetro no es válido".System.Drawing.Graphics.DrawString - "El parámetro no es válido" excepción

Tenga en cuenta que la fuente, lo mejor que puedo decir está construida correctamente (estoy usando Arial a 10pt), el tamaño rect es positivo y válido, el pincel es un SolidBrush blanco y las banderas de formato no afectan la salida; es decir, si excluyo las banderas de formato de la llamada, sigo teniendo un error

llamada el cordón está cerca de la parte inferior

public ActionResult RenderText(
    string fontFamily, 
    float pointSize, 
    string foreColor, 
    string backColor, 
    bool isBold, 
    bool isItalic, 
    bool isVertical, 
    string align, 
    string[] allText, 
    int textIndex) 
{ 
    // method renders a horizontal or vertical text image, taking all the text strings that will be rendered in each image 
    // and sizing the final bitmap according to which text would take the most space, thereby making it possible to render 
    // a selection of text images all at the same size. 

    Response.ContentType = "image/png"; 

    var fmt = StringFormat.GenericTypographic; 
    if(isVertical) 
     fmt.FormatFlags = StringFormatFlags.DirectionVertical; 

    Func<string,StringAlignment> getAlign = (s => { 
     switch(s.ToLower()) 
     { 
      case "right": return StringAlignment.Far; 
      case "center": return StringAlignment.Center; 
      default: return StringAlignment.Near; 
     } 
    }); 
    fmt.LineAlignment = isVertical ? StringAlignment.Center : getAlign(align); 
    fmt.Alignment = isVertical ? getAlign(align) : StringAlignment.Center; 

    var strings = (allText ?? new string[0]).Where(t => t.Length > 0).ToList(); 
    if(strings.Count == 0) 
     strings.Add("[Missing Text]"); 

    FontStyle style = FontStyle.Regular; 
    if(isBold) 
     if(isItalic) 
      style = FontStyle.Bold | FontStyle.Italic; 
     else 
      style = FontStyle.Bold; 
    else if(isItalic) 
     style = FontStyle.Italic; 

    Font font = new Font(fontFamily, pointSize, style, GraphicsUnit.Point); 
    Color fc = foreColor.IsHexColorString() ? foreColor.ToColorFromHex() : foreColor.ToColor(); 
    Color bc = backColor.IsHexColorString() ? backColor.ToColorFromHex() : backColor.ToColor(); 

    var maxSize = new Size(0,0); 
    using(var tmp = new Bitmap(100, 200)) 
     using(var gfx = Graphics.FromImage(tmp)) 
      foreach(var txt in strings) 
      { 
       var size = gfx.MeasureString(txt, font, 1000, fmt); 
       maxSize = new Size(
        Math.Max(Convert.ToInt32(isVertical ? size.Height : size.Width), maxSize.Width), 
        Math.Max(Convert.ToInt32(isVertical ? size.Width : size.Height), maxSize.Width) 
       ); 
      } 

    using(var bmp = new Bitmap(maxSize.Width, maxSize.Height)) 
    { 
     using(var gfx = Graphics.FromImage(bmp)) 
     { 
      gfx.CompositingMode = CompositingMode.SourceCopy; 
      gfx.CompositingQuality = CompositingQuality.HighQuality; 
      gfx.SmoothingMode = SmoothingMode.HighQuality; 
      gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; 

      var rect = new RectangleF(new PointF(0,0), maxSize); 
      gfx.FillRectangle(new SolidBrush(bc), rect); 
      gfx.DrawString(strings[textIndex], font, new SolidBrush(fc), rect, fmt); 
     } 
     bmp.Save(Response.OutputStream, ImageFormat.Png); 
    } 
    return new EmptyResult(); 
} 
+1

Sólo una nota: nueva SolidBrush (fc) se fuga de un recurso de pincel, que necesita un bloque usando también. –

+1

Solo un consejo: tuve el mismo error "El parámetro no es válido" y llegué a este hilo. En mi caso no tenía nada que ver con la respuesta aceptada, era porque estaba pasando a DrawString una instancia Dispuesta de fuente o pincel. La excepción no es realmente útil ... – AFract

Respuesta

14

Pues supe que la causa del problema... Algo muy oscuro. El código funciona cuando elimino esta línea:

gfx.CompositingMode = CompositingMode.SourceCopy; 
+0

¡Ahorro de vida! Esto tiene sentido en realidad, estoy seguro de que necesita fusión habilitada para dibujar texto, pero sería bueno si el mensaje de error menciona algo sobre eso :-) – eodabash

4

Lo que podría ayudar mientras se depura, es hacer los métodos más pequeños. Por ejemplo, podría reemplazar

FontStyle style = FontStyle.Regular; 
if(isBold) 
    if(isItalic) 
     style = FontStyle.Bold | FontStyle.Italic; 
    else 
     style = FontStyle.Bold; 
else if(isItalic) 
    style = FontStyle.Italic; 

por

FontStyle style = GetFontStyle(isBold, isItalic); 

y

public FontStyle GetFontStyle(bool isBold, bool isItalic) 
{ 
    if(isBold) 
     if(isItalic) 
      return FontStyle.Bold | FontStyle.Italic; 
     else 
      return FontStyle.Bold; 
    else if(isItalic) 
     return FontStyle.Italic; 
    else 
     return FontStyle.Regular; 
} 

Hace que el código sea más fácil de leer y que hace que sea más fácil para que otros le ayuden.

¡Realmente no se trata de ofender!

Saludos cordiales, Ans Vlug

Cuestiones relacionadas