Я работаю над WinFormsProject, все работает, но когда мне нужно распечатать счет, появляется это исключение
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
Эта ошибка появилась, когда я сделал метод асинхронным для работы с супабазой. Я проверил, что все значения не равны нулю. Я думаю проблема в графике:
В этом методе:
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;
}
Это значение, когда я запускаю проект: Graphics.NativeGraphics = 0x0000024f04c04230
И когда я пытаюсь распечатать счет, он переходит к: Graphics.NativeGraphics = 0x0000000000000000
Это мой метод:
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.Dispose();
. Это не копия, это фактическая ссылка на объект Graphics. Вы не избавляетесь от него. Это также бесполезно: Graphics graphics = e.Graphics;
, но безвредно. После этого посмотрите, сможете ли вы вызвать GenerateTicket()
до того, как будет сгенерировано событие PrintPage
.
@AN Независимо от того, какую перегрузку DrawString() вы вызываете, в конце концов выполняется именно она.
Спасибо за помощь ребята. Я думаю, что на самом деле это произошло из-за асинхронного ожидания другого метода (GenerateTicket()). Я попробовал это с фиксированным значением в неасинхронном исполнении, и это сработало. Если это не сработает, я вернусь сюда
Этот вид графической процедуры не должен быть асинхронным. Вы читали примечание о graphics.Dispose();
? Вы не сможете этого сделать, никогда. Вы избавляетесь только от созданного вами объекта, а не от объектов, предоставленных инфраструктурой (подумайте о стандартных объектах, если это поможет).
Вы не можете использовать async void
в обработчике PrintPage
, потому что объект Graphics
поступает от вызывающего объекта, и они распечатают документ и утилизируют его, как только вы вернетесь, что происходит в первый раз await
. Таким образом, вам придется получить это значение где-то еще, прежде чем этот обработчик запустится.
Также:
e.Graphics
.font
и brush
с помощью using
, если вы их создаете. Вам не нужно этого делать, если они уже существуют в системе, поскольку это не требуется.try
catch
, снаружи можно использовать один.if
означает, что вы можете удалить else
.font
, brush
и e.Graphics
не будут null
, вам не нужно это проверять.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;
}
Я вижу одну интересную вещь: подпись метода —
DrawString(String s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format)
, но вы передаете(string, Font, Brush, float, float)
. Как вы думаете, почему он вызывает это вместо метода, который вы ожидаете?