I am having problems creating a protected variable that can be access and updated by an external method.
In other words, I have got a print method that prints multiple pages.
I needs an external variable to initialize this method and keep track of the pages.
Is it possible someone could get me started in coding this class? as I knowledge on OOP is limited
Below is the print method
Thanks in advance
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics graphics = e.Graphics;
int ypos = 78;
Font f1 = new Font("Arial", 14, FontStyle.Bold, GraphicsUnit.Pixel);
Brush brush = new SolidBrush(Color.LightSlateGray);
graphics.FillRectangle(brush, new Rectangle(10, 10, 770, 50));
Pen blackpen = new Pen(Color.Black);
Pen graypen = new Pen(Color.LightGray);
Pen redpen = new Pen(Color.Red);
graphics.DrawRectangle(blackpen, new Rectangle(10, 10, 770, 50));
Brush B = new SolidBrush(listView1.ForeColor);
graphics.DrawLine(blackpen, 10, 10, 10, 1132);
graphics.DrawString("FORENAME", f1, Brushes.Black, new Point(20, 25));
graphics.DrawLine(blackpen, 130, 10, 130, 1132);
graphics.DrawString("SURNAME", f1, Brushes.Black, new Point(140, 25));
graphics.DrawLine(blackpen, 290, 10, 290, 1132);
graphics.DrawString("EXT.", f1, Brushes.Black, new Point(300, 25));
graphics.DrawLine(blackpen, 380, 10, 380, 1132);
graphics.DrawString("JOB TITLE", f1, Brushes.Black, new Point(410, 25));
graphics.DrawLine(blackpen, 780, 10, 780, 1132);
int[] X = { 15, 140, 300, 390, 720 };
int Y = 60;
f1 = listView1.Font;
for (int I = 0; I < listView1.Items.Count; I++){
for (int J = 0; J < listView1.Items[I].SubItems.Count - 1; J++){
graphics.DrawString(listView1.Items[I].SubItems[J].Text, f1, B, X[J], Y);
}
}
Y += f1.Height;
graphics.DrawLine(graypen, 10, ypos, 780, ypos);
ypos = ypos + 17;
if (ypos > 1132){
e.HasMorePages = true;
return;
}
graphics.Dispose();
}
Try below function, and call print event
public void PrintDocument()
{
try
{
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler
(this.printDocument1_PrintPage);
pd.Print();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Related
I'm writing a program in C# which takes information of items from Listview and print it based on the quantity of these items. My problem is that I would like to print a document in multiple pages in c#.
Here is my code:
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
//frame
e.Graphics.DrawRectangle(Pens.Black, 30, 30, 757, 1080);
//rows
e.Graphics.DrawLine(Pens.Black, 30, 184, 787, 184);
e.Graphics.DrawLine(Pens.Black, 30, 338, 787, 338);
e.Graphics.DrawLine(Pens.Black, 30, 492, 787, 492);
e.Graphics.DrawLine(Pens.Black, 30, 646, 787, 646);
e.Graphics.DrawLine(Pens.Black, 30, 800, 787, 800);
e.Graphics.DrawLine(Pens.Black, 30, 955, 787, 955);
//columns
e.Graphics.DrawLine(Pens.Black, 282, 30, 282, 1110);
e.Graphics.DrawLine(Pens.Black, 534, 30, 534, 1110);
int rows_loc = 35;
int cols_loc = 70;
int lable_index = 0;
foreach (ListViewItem item in listView1.Items)
{
for (int quantity = 1; quantity < (Convert.ToInt32(item.SubItems[1].Text) + 1); quantity++)
{
Font font = new System.Drawing.Font("Arial", 16);
SolidBrush black = new SolidBrush(Color.Black);
Zen.Barcode.Code128BarcodeDraw barcode1 = Zen.Barcode.BarcodeDrawFactory.Code128WithChecksum;
Image barcode_image = barcode1.Draw(item.SubItems[2].Text, 20);
e.Graphics.DrawImage(barcode_image, 40f + cols_loc, 29f + rows_loc);
e.Graphics.DrawString(item.Text, font, black, 60f + cols_loc, 0f + rows_loc);
lable_index++;
row_index = (int)(lable_index / 3);
col_index = lable_index % 3;
rows_loc = 35 + ((row_index) * 155);
cols_loc = 70 + (250 * col_index);
if (rows_loc >= e.PageSettings.PrintableArea.Height)
{
e.HasMorePages = true;
rows_loc = 35;
return;
}
else
{
e.HasMorePages = false;
}
}
}
}
But got the page looks like the figure below with infinite number of pages! I would be very appreciated if someone can help.
Thanks
i am trying to print a invoice from application for my dads business, i am using the following code to print the invoice.
My attempt is below:
{
int y = 470;
while (i < dataGridView1.RowCount)
{
e.Graphics.DrawString(dataGridView1.Rows[i].Cells["ProductName"].Value.ToString(), DefaultFont, Brushes.Black, new Point(35, y));
e.Graphics.DrawString(dataGridView1.Rows[i].Cells["Desc"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(250, y));
e.Graphics.DrawString(dataGridView1.Rows[i].Cells["Quantity"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(600, y));
e.Graphics.DrawString(dataGridView1.Rows[i].Cells["UnitPrice"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(650, y));
e.Graphics.DrawString(dataGridView1.Rows[i].Cells["Tax"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(700, y));
e.Graphics.DrawString(dataGridView1.Rows[i].Cells["Total"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(650, y));
y = y + 20;
if (y >= pageHeight)
{
e.HasMorePages = true;
y = 0;
i++;
return;
}
else
{
e.HasMorePages = false;
}
i++;
}
}
i here is a global variable
private int i = 0;
when i click on preview button i get the output as expected but when i print it on paper only the content in the while loop is not printed. i tried using a local variable instead j of global variable as shown below and it worked.
for (int j=0; j < dataGridView1.RowCount; j++)
{
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["ProductName"].Value.ToString(), DefaultFont, Brushes.Black, new Point(35, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["Desc"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(250, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["Quantity"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(600, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["UnitPrice"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(650, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["Tax"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(700, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["Total"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(650, y));
y = y + 20;
}
but i don't know how to add new pages if the item to be included exceeds the page height. please some help.
after iterating through the code step by step i found that the code tp print the preview is run again while printing the form. so i just had to initialize the i value to 0 so that it starts printing from the beginning.
here is the code which solved it
int j;
for (j=i; j < dataGridView1.RowCount && y<e.MarginBounds.Bottom; j++)
{
e.Graphics.DrawString(e.MarginBounds.Bottom.ToString(), DefaultFont, Brushes.Black, new Point(100, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["ProductName"].Value.ToString(), DefaultFont, Brushes.Black, new Point(35, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["Desc"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(220, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["Quantity"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(770, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["UnitPrice"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(620, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["Tax"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(670, y));
e.Graphics.DrawString(dataGridView1.Rows[j].Cells["Total"].Value.ToString(), new Font("Arial", 15, FontStyle.Bold), Brushes.Black, new Point(720, y));
y = y + 20;
}
if (j < dataGridView1.RowCount)
{
e.HasMorePages = true;
i=j;
}
else
{
e.HasMorePages = false;
i = 0;
}
I fill up a datagridview and after that I print out the list from there some extra fix string fields. The first two printing finishing fast but after that 3-4 is slowing down very much(sometimes it freezing).
I think some buffer or something fills up and i have to empty it but how? If I tried to print via pdf printer the first file size is normal ~200KB second is 1MB and the third is 4-6MB the fourth is so big it is freezing.
It is only one page maximum two page long list. Can someone help me to find the problem and offer a solution or more?
private void button1_Click(object sender, EventArgs e)
{
printDocument1.Print();
}
Print button
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
Bitmap bmp = Properties.Resources.ugro;
Image newImage = bmp;
e.Graphics.DrawImage(newImage, 700, 20, 100, 100);
Bitmap bmp1 = Properties.Resources.line_1;
Image newImage1 = bmp1;
e.Graphics.DrawImage(newImage1, 20, 80, 700, 1);
e.Graphics.DrawString("Text", new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(280, 20));
e.Graphics.DrawString(lbl_datum.Text, new Font("Arial", 8, FontStyle.Bold), Brushes.Black, new Point(20, 20));
// e.Graphics.DrawString("Text:", new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(20, 100));
//e.Graphics.DrawString(txt_BID.Text, new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(160, 80));
//e.Graphics.DrawString(txt_ID.Text, new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Point(160, 100));
DataGridViewCell cell = null;
foreach (DataGridViewCell selectedCell in dataGridView1.SelectedCells)
{
cell = selectedCell;
break;
}
if (cell != null)
{
DataGridViewRow row = cell.OwningRow;
}
e.Graphics.DrawString("Name", new Font("Arial", 10, FontStyle.Bold), Brushes.Black, new Point(40, 60));
e.Graphics.DrawString("Height(cm)", new Font("Arial", 10, FontStyle.Bold), Brushes.Black, new Point(150, 60));
e.Graphics.DrawString("Weight(kg)", new Font("Arial", 10, FontStyle.Bold), Brushes.Black, new Point(280, 60));
e.Graphics.DrawString("Text(cm)", new Font("Arial", 10, FontStyle.Bold), Brushes.Black, new Point(410, 60));
int height = 0;
//int width = 0;
//e.Graphics.FillRectangle(Brushes.DarkGray,new Rectangle(100,100,dataGridView1.Columns[0].Width,dataGridView1.Rows[0].Height));
// e.Graphics.DrawString(dataGridView1.Columns[0].HeaderText.ToString(), new Font("Arial", 12, FontStyle.Bold), Brushes.Black, new Rectangle(420, 80, dataGridView1.Columns[0].Width,dataGridView1.Rows[1].Height));
height = 80;
while (i < dataGridView1.Rows.Count)
{
if (height > e.MarginBounds.Height)
{
e.HasMorePages = true;
return;
}
height += 20;
//e.Graphics.DrawString(dataGridView1.Rows[i].Cells[0].FormattedValue.ToString(), dataGridView1.Font, Brushes.Black, new Rectangle(20, height, dataGridView1.Columns[0].Width, 20));
e.Graphics.DrawString(dataGridView1.Rows[i].Cells[0].FormattedValue.ToString(), dataGridView1.Font, Brushes.Black, new Rectangle(20, height, dataGridView1.Columns[0].Width+50, 40));
string sign = String.Format("_____________");
e.Graphics.DrawString(sign, dataGridView1.Font, Brushes.Black, new Rectangle(150, height, dataGridView1.Columns[0].Width + 100, 40));
e.Graphics.DrawString(sign, dataGridView1.Font, Brushes.Black, new Rectangle(280, height, dataGridView1.Columns[0].Width + 100, 40));
e.Graphics.DrawString(sign, dataGridView1.Font, Brushes.Black, new Rectangle(410, height, dataGridView1.Columns[0].Width + 100, 40));
i++;
printDocument1.PrintPage += new PrintPageEventHandler(printDocument1_PrintPage);
}
i = 0;
}
Which variable is causing my problem?
I'm creating a label with Graphics and printing it with PrintDocument, before i didn't had any problems because the information on the label was repeated multiple times so i would just set copies and everything would work fine.
But now each label has a different information so it freezes the ui because i have to loop PrintDocument.Print() multiple times instead of setting copies.
i tried:
Task t = new Task(() =>
{
for (int i = 0; i < Copies; i++)
{
printDocument1.Print();
Label_Copies++;
}
});
t.Start();
I'm drawing the label on printDocument1_PrintPage with this code:
int base_y = 5;
int base_x = 7;
int fontsize_bold = 8;
int fontsize_regular = 7;
RectangleF baserect = new RectangleF(base_x, base_y + 20, 0, 0);
SolidBrush whiteBrush = new SolidBrush(System.Drawing.Color.White);
SolidBrush blackBrush = new SolidBrush(System.Drawing.Color.Black);
string font = "Cabriolli";
Pen mypen = new Pen(blackBrush);
e.Graphics.FillRectangle(whiteBrush, new Rectangle(0, 0, 320, 130));
//e.Graphics.DrawRectangle(mypen, 1, 1, 225, 140);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.DrawString("REMETENTE:",
new Font(font, fontsize_regular, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x, base_y, 0, 0));
base_y += 10;
e.Graphics.DrawString("BETA COMERCIAL IMPORTADORA LTDA",
new Font(font, fontsize_bold, System.Drawing.FontStyle.Bold),
Brushes.Black, new RectangleF(base_x, base_y, 0, 0));
base_y += 15;
e.Graphics.DrawString("DESTINATARIO:",
new Font(font, fontsize_regular, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x, base_y, 0, 0));
base_y += 10;
e.Graphics.DrawString(Etiqueta_Destinatario, // *cliente
new Font(font, fontsize_bold, System.Drawing.FontStyle.Bold),
Brushes.Black, new RectangleF(base_x, base_y, 0, 0));
base_y += 15;
e.Graphics.DrawString("NOTA FISCAL:",
new Font(font, fontsize_regular, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x, base_y + 3, 0, 0));
e.Graphics.DrawString(Etiqueta_Nota, // *nota
new Font(font, 10, System.Drawing.FontStyle.Bold),
Brushes.Black, new RectangleF(base_x + 68, base_y, 0, 0));
base_y += 15;
e.Graphics.DrawString("PEDIDO:",
new Font(font, fontsize_regular, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x, base_y + 3, 0, 0));
e.Graphics.DrawString(Etiqueta_Pedido, // *pedido
new Font(font, 10, System.Drawing.FontStyle.Bold),
Brushes.Black, new RectangleF(base_x + 43, base_y, 0, 0));
base_y += 15;
e.Graphics.DrawString("Etiqueta numero:",
new Font(font, fontsize_regular, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x + 140, base_y - 20, 0, 0));
if (Copias.Checked)
{
e.Graphics.DrawString(Etiqueta_Copias.ToString(),
new Font(font, 15, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x + 140, base_y, 0, 0));
}
else
{
e.Graphics.DrawString(Etiqueta_Copia.ToString(),
new Font(font, 15, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x + 140, base_y, 0, 0));
}
e.Graphics.DrawString("VOLUMES:",
new Font(font, fontsize_regular, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x, base_y + 3, 0, 0));
e.Graphics.DrawString(peças_textbox.Text, // *quantidade
new Font(font, 10, System.Drawing.FontStyle.Bold),
Brushes.Black, new RectangleF(base_x + 53, base_y, 0, 0));
base_y += 25;
e.Graphics.DrawString("TRANSPORTADORA:",
new Font(font, fontsize_regular, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x, base_y, 0, 0));
base_y += 14;
e.Graphics.DrawString(nota_transportadora_combobox.Text, // *transportadora
new Font(font, 10, System.Drawing.FontStyle.Bold),
Brushes.Black, new RectangleF(base_x, base_y, 0, 0));
whiteBrush.Dispose();
blackBrush.Dispose();
mypen.Dispose();
but it doesn't work is there a way to fix it?
-the information comes from the ui
-500~ labels
-the only information that changes from label to label in those copies is
if (Copias.Checked)
{
e.Graphics.DrawString(Etiqueta_Copias.ToString(),
new Font(font, 15, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x + 140, base_y, 0, 0));
}
else
{
e.Graphics.DrawString(Etiqueta_Copia.ToString(),
new Font(font, 15, System.Drawing.FontStyle.Regular),
Brushes.Black, new RectangleF(base_x + 140, base_y, 0, 0));
}
its basically a counter for the label number...
As I see it, your code, if we ignore the printer's spooling side, is pure WinForms UI.
Since that the work is multiplied, let's say by a 100 copies, it becomes too much Continous UI.
Tasking isn't helping you because I think the printing side is "fire and forget", so even if the printing took 30 seconds per sticker, the printing side would return immediately, and let the UI start it's heavy work on the next sticker, almost immediately after it finishes the last one.
let's say the UI has to work 1 second per sticker, you are looking at a 100 seconds UI blocking...
My suggestion:
Rely on the fact that the printing behind takes 20 seconds: Launch the printing using a timer instead of a loop. Set it to 5, 10 or 20 seconds (match with your printer's speed). Each time you will fire the timer, it will UI process 1 sticker only, and then rest in peace for 5, 10, or 20 seconds...
Printer prints every odd page in portrait orientation.
private void Form1_Loaded(object sender, EventArgs e)
{
PaperSize ps = new PaperSize("Custom", 700, 325);
printDocument.DefaultPageSettings.PaperSize = ps;
label1.Text = Convert.ToString(printDocument.DefaultPageSettings.PaperSize);
//printDocument.DefaultPageSettings.Landscape = true;
printDocument.PrinterSettings.DefaultPageSettings.Landscape = true;
}
private void DrawGridBody(Graphics g, int y_value)
{
int x_value;
for (int i = 0; (i < NUM_ROWS_PER_PAGE) && ((i+m_printedRows) < ((DataTable)dataGridView.DataSource).Rows.Count); ++i)
{
DataRow dr = ((DataTable)dataGridView.DataSource).Rows[i + m_printedRows];
x_value = 0;
string text = dr.ItemArray.ElementAt(0).ToString();
g.DrawString(text+"**", this.Font, Brushes.Black, (float)x_value, (float)y_value + 10f);
y_value += ROW_HEIGHT;
g.DrawString("page " + Convert.ToString(m_printedRows), new Font("Lucidia Console", 14, FontStyle.Bold), Brushes.Black, 60, 10);
g.DrawString("1 " + dr.ItemArray.ElementAt(0).ToString(), new Font("Lucidia Console", 10), Brushes.Black, new Point(370, 20));
g.DrawString("2 " + dr.ItemArray.ElementAt(0).ToString(), new Font("Lucidia Console", 10), Brushes.Black, new Point(390, 46));
g.DrawString("3 " + dr.ItemArray.ElementAt(0).ToString(), new Font("Lucidia Console", 10), Brushes.Black, new Point(30, 40));
g.DrawString(dr.ItemArray.ElementAt(1).ToString(), new Font("Lucidia Console", 10), Brushes.Black, new Point(70, 180));
g.DrawString(dr.ItemArray.ElementAt(2).ToString() + " " + dr.ItemArray.ElementAt(3).ToString(), new Font("Lucidia Console", 10), Brushes.Black, new Point(70, 202));
g.DrawString(dr.ItemArray.ElementAt(4).ToString(), new Font("Lucidia Console", 10), Brushes.Black, new Point(70, 224));
g.DrawString(dr.ItemArray.ElementAt(5).ToString(), new Font("Lucidia Console", 10), Brushes.Black, new Point(550, 285));
g.DrawString("***********", new Font("Lucidia Console", 10), Brushes.Black, new Point(550, 300));
g.DrawString("***********", new Font("Lucidia Console", 10), Brushes.Black, new Point(550, 315));
}
m_printedRows += NUM_ROWS_PER_PAGE;
printDocument.PrinterSettings.DefaultPageSettings.Landscape = true;
printDocument.DefaultPageSettings.Landscape = true;
}
private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int rowPosition = SPACE_ABOVE_HEADER;
rowPosition += ROW_HEIGHT;
// draw each row
DrawGridBody(e.Graphics, rowPosition);
// see if there are more pages to print
if (MoreRowToPrint())
e.HasMorePages = true;
else
m_printedRows = 0;
}
private bool MoreRowToPrint()
{
return ((DataTable)dataGridView.DataSource).Rows.Count > m_printedRows;
}