Search code examples
c#winforms.net-8.0

Getting error in DrawString (C# WinForms)


I´m working on a WinFormsProject, everything works, but when I need to print the invoice, this exception shows up

System.ArgumentException: Parameter is not valid.

   at System.Drawing.Graphics.CheckErrorStatus(Int32 status)

   at System.Drawing.Graphics.DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)

   at Panaderia_Supabase.Forms.Cobranza.PrintPage(Object sender, PrintPageEventArgs e) in D:\Dev\Nueva carpeta\Panaderia-Supabase\Forms\Cobranza.cs:line 217

This error showed up when I made the method asynchornous, to work with supabase. I checked that all the values are not null. I think the problem is with graphics:

In this method:

    public float GetHeight(Graphics graphics)
    {
        ArgumentNullException.ThrowIfNull(graphics, "graphics");
        if (graphics.NativeGraphics == IntPtr.Zero)
        {
            throw new ArgumentException("graphics");
        }
        SafeNativeMethods.Gdip.CheckStatus(SafeNativeMethods.Gdip.GdipGetFontHeight(new HandleRef(this, NativeFont), new HandleRef(graphics, graphics.NativeGraphics), out var size));
        return size;
    }

This is the value when i run the project: graphics.NativeGraphics = 0x0000024f04c04230

And when i try to print the invoice it goes to: graphics.NativeGraphics = 0x0000000000000000

This is my method:

    private async void PrintPage(object sender, PrintPageEventArgs e)
      {
      try
        {
        // Verifica si el objeto Graphics es válido
        if (e.Graphics == null)
          {
          MessageBox.Show("Objeto Graphics no válido.");
          return;
          }

        Graphics graphics = e.Graphics;
        Font font = new("Courier Mono", 10, FontStyle.Regular);
        Brush brush = Brushes.Black;
        // Generar el ticket
        string ticket = await GenerateTicket();
        if (string.IsNullOrEmpty(ticket))
          {
          MessageBox.Show("El ticket no se ha generado correctamente.");
          return;
          }

        float yPos = 10;
        float xPos = 10;
        float lineHeight = font.Height;

        try
          {
          MessageBox.Show($"Altura de la línea: {lineHeight}");
          }
        catch (Exception ex)
          {
          MessageBox.Show($"Error al obtener la altura de la línea: {ex.Message}");
          return;
          }

        try
          {
          using (StringReader reader = new StringReader(ticket))
            {
            string line;
            while ((line = reader.ReadLine()) != null)
              {
              if (yPos + lineHeight <= e.MarginBounds.Bottom)
                {
                try
                  {
                  if (string.IsNullOrEmpty(line) || font == null || brush == null || xPos == 0 || yPos == 0)
                    {
                    MessageBox.Show($"Valor nulo: line - {line}, font - {font}, brush - {brush} , xPos - {xPos}, yPos - {yPos}");
                    }
                  else
                    graphics.DrawString(line, font, brush, xPos, yPos);
                  }
                catch (Exception ex)
                  {
                  MessageBox.Show($"{ex}");
                  return;
                  }
                yPos += lineHeight;
                }
              else
                {
                e.HasMorePages = true;
                return;
                }
              }
            }
          }
        catch (Exception ex)
          {
          MessageBox.Show($"Error durante el proceso de impresión: {ex.Message}");
          }

        graphics.Dispose();
        font.Dispose();
        brush.Dispose();
        e.HasMorePages = false;
        }
      catch (Exception ex)
        {
        MessageBox.Show($"Error en PrintPage: {ex.Message}");
        }
      }

graphics when i´m using it  " graphics.DrawString(line, font, brush, xPos, yPos); it is like this"

If you need some more source code, just ask for it and I´ll provide. Thanks!

I´ve checked nullity of all the parameters, tried to pass fixed values as parameters also doesn´t worked. And the exceptions messages are not very helpful, so I don´t know what to do.


Solution

  • You can't use async void in the PrintPage handler, because the Graphics object comes from the caller, and they will print the document and dispose it as soon as you return, which happens at the first await. So you are going to have to get that value elsewhere before this handler even runs.

    Also:

    • Do not dispose e.Graphics.
    • Do dispose font and brush with using if you are creating them. You don't need to if they are the pre-existing system ones, as this is a no-op.
    • You can also significantly simplify the logic:
      • You don't need so many try catchs, you can use a single one on the outside.
      • Inverting some of the ifs means you can remove the elses.
    • font and brush and e.Graphics aren't going to be null, you don't need to check for that.
    private void PrintPage(object sender, PrintPageEventArgs e)
    {
        try
        {
            string ticket = GetAlreadyGeneratedTicket();    // you can't use async while using the Graphics
            if (string.IsNullOrEmpty(ticket))
            {
                MessageBox.Show("El ticket no se ha generado correctamente.");
                return;
            }
    
            Graphics graphics = e.Graphics;
            using Font font = new("Courier Mono", 10, FontStyle.Regular);
            Brush brush = Brushes.Black;
    
            float yPos = 10;
            float xPos = 10;
            float lineHeight = font.Height;
    
            MessageBox.Show($"Altura de la línea: {lineHeight}");
    
            using StringReader reader = new StringReader(ticket);
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                if (yPos + lineHeight > e.MarginBounds.Bottom)
                {
                    e.HasMorePages = true;
                    return;
                }
    
                if (string.IsNullOrEmpty(line) || xPos == 0 || yPos == 0)
                {
                    MessageBox.Show($"Valor nulo: line - {line}, font - {font}, brush - {brush} , xPos - {xPos}, yPos - {yPos}");
                }
                else
                    graphics.DrawString(line, font, brush, xPos, yPos);
    
                yPos += lineHeight;
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show($"Error durante el proceso de impresión: {ex.Message}");
        }
    
        e.HasMorePages = false;
    }