Reputation: 47
I have a little issue with printing in c# and .Net. I have made it work with the regular printing event from the System.Drawing.Printing event, which worked fine, but now, I want to do it a different way.
Before I would print directly from a winform program, where I would declare a printdocument on a winform element which contains all the information, and then step by step redraw it onto a graphics object in order to then print it. Since this is happening in the main code, and is not very flexible, I decided to write a library for that. The library takes a printer name, grabs the printer's maximum paper width and paper height, creates a graphics object with it, paints it all white, and then does the same steps as described before, draws the entire information onto it step by step.
I wrote a function that returns that graphics object, and now I want to pass this pre-built graphics object to a printdocument, in order to print it. This, however, isn't working. I've looked through Microsoft documentation and found this little morsel from Microsoft, which didn't really help me at all. Further looking through stack overflow also didn't help my cause, because I found nobody who ran into a similar issue, or attempted what I'm trying to do.
The code is as follows: This function right here triggers the event for the printer. It contains a few printer specific functions from the library I wrote which seem to work fine. The Messageboxes are just there to show if the paper width and height are properly grabbed.
private void btnPrinter_Click(object sender, EventArgs e)
{
//Test functions to return paper width and height
MessageBox.Show(GebeDrucker.returnwidth().ToString());
MessageBox.Show(GebeDrucker.returnheight().ToString());
//Setting text alignment
GebeDrucker.F_Alignment(C_BillPrint.Alignments.CENTER);
GebeDrucker.F_DrawHeading("Company name placeholder", new Font("Arial", 16));
GebeDrucker.F_DrawLogo(new Bitmap(Bitmap.FromFile(@"C:/Imagelocation/Image.png")));
GebeDrucker.F_Drawtable(new Font("Roboto condensed", 10));
GebeDrucker.F_QR("Hier ist min code");
PaperSize Custom = new PaperSize("Printi", panel1.Width, Convert.ToInt32(Math.Round(panel1.Height*1.01)));
//printDocument1.DefaultPageSettings.PaperSize = Custom;
PrintPreviewDialog pb = new PrintPreviewDialog();
pb.Document = printDocument1;
pb.ShowDialog();
printDocument1.Print();
GVProduct.Rows.Clear();
GVReceipt.Rows.Clear();
Calc();
//panel1.Height = 490;
}
The following function just returns the Graphics object:
/// <summary>
/// Function to return the Graphics object Bill.
/// </summary>
/// <returns>The Bill, represented as a Graphic.</returns>
public Graphics F_ReturnGraphics()
{
return this.bill;
}
And here, I try to override the e.Graphics from the event with my own graphics object when printing is triggered. The stuff that is commented out is the previous way of doing things, drawing on it step by step, Which works fine, but isn't very flexible.
public void printdoc1_PrintPage(object sender, PrintPageEventArgs e)
{
/*
string company = "Company Placeholder Text";
string Header = " Artikel Anzahl Gesamt";
string Seperator = "____________________________________";
string Total = "Gesamt:";
Font ComCom = new Font("Roboto condensed", 16);
Font Heading = new Font("Roboto condensed", 10);
SolidBrush drawBrush = new SolidBrush(Color.Black);
float C_X = 5.0F;
float C_Y = 5.0F;
e.Graphics.DrawString(company, ComCom, drawBrush, C_X, C_Y);
float L_X = 15.0F;
float L_Y = 35.0F;
Size Loco = new Size(180, pCompanyImage.Image.Height-10);
Bitmap Logo = new Bitmap(pCompanyImage.Image, Loco);
e.Graphics.DrawImage(Logo, L_X, L_Y);
float DH_X = 0.0F;
float DH_Y = 140.0F;
e.Graphics.DrawString(Header, Heading, drawBrush, DH_X, DH_Y);
float IT_X = 0.0F;
float IT_Y = 165.0F;
float IM_X = 114.0F;
float IR_X = 166.0F;
for (int i = 0; i < GVReceipt.RowCount - 1; i++)
{
e.Graphics.DrawString(" "+GVReceipt.Rows[i].Cells[0].Value.ToString(), Heading, drawBrush, IT_X, IT_Y);
e.Graphics.DrawString(GVReceipt.Rows[i].Cells[1].Value.ToString() + "x", Heading, drawBrush, IM_X, IT_Y);
e.Graphics.DrawString(GVReceipt.Rows[i].Cells[2].Value.ToString() + "€", Heading, drawBrush, IR_X, IT_Y);
IT_Y = IT_Y + (GVReceipt.RowCount - 2) * GVReceipt.Rows[0].Height;
}
float S_X = 6.0F;
float S_Y = IT_Y + 10.0F;
e.Graphics.DrawString(Seperator, Heading, drawBrush, S_X, S_Y);
float T_X = 15.0F;
float T_Y = S_Y + 20.0F;
float Su_X = 120.0F;
e.Graphics.DrawString(Total, ComCom, drawBrush, T_X, T_Y);
e.Graphics.DrawString(Calc() + "€", ComCom, drawBrush, Su_X, T_Y);
float SS_Y = T_Y + 20.0F;
e.Graphics.DrawString(Seperator, Heading, drawBrush, S_X, SS_Y);
*/
Graphics benis = e.Graphics;
benis = GebeDrucker.F_ReturnGraphics();
}
Trying to directly override e.Graphics doesn't work since it's protected. I also don't want to pass my graphics as a Bitmap, because then I'd loose a lot of resolution, and the document is printed out blurry. I don't know if printing from a class library is even possible, I assume not, because that requires the System.Forms library which I try to avoid here, so I was thinking maybe writing a custom printing event that takes a graphics object and tries to print that out, but I don't know how to construct that. Maybe my way of thinking is wrong entirely and this isn't working at all or requires a workaround. This is why I'm asking for help here, and anything at all would be highly appreciated.
Upvotes: 0
Views: 752
Reputation: 38785
As TaW mentioned, Graphics
doesn't actually contain and image information. It's just a tool for drawing graphics onto an existing canvas (e.g. a Bitmap
).
One solution You could simply pass Graphics
to F_ReturnGraphics
:
GebeDrucker.F_ReturnGraphics(e.Graphics);
And then the method would look like this:
public void F_ReturnGraphics(Graphics gfx)
{
gfx.Clear(Color.White); // etc
}
You could also return the Graphics
object again if you wanted to:
public Graphics F_ReturnGraphics(Graphics gfx)
{
gfx.Clear(Color.White); // etc
return gfx;
}
Upvotes: 1