Good day to all,
I have an application that creates a report for daily time record of an employee.
The problem is all of the pages in printpreview dialog were overwritting by every pages that available in printing. how can i possibly solve this kind of issue? The content of page 1 is for page 1, page 2 is for page 2 only and vise versa.
Here is my code for printing:
private void simpleButtonOk_Click(object sender, EventArgs e)
{
try
{
countPage = 0;
CoolPrintPreviewDialog printPreview = new CoolPrintPreviewDialog();
PrintDocument doc = new PrintDocument();
doc.PrintPage += new PrintPageEventHandler(doc_PrintPage);
printPreview.Document = doc;
Form p = (Form)printPreview;
p.WindowState = FormWindowState.Maximized;
p.ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void doc_PrintPage(object sender, PrintPageEventArgs e)
{
try
{
for (int i = 1; i <= countEmployee; i++)
{
Font fontName = new Font("Calibri", 12, FontStyle.Bold);
Font fontPosition = new Font("Calibri", 12, FontStyle.Regular);
Brush colorBrush = new SolidBrush(Color.Black);
e.Graphics.DrawString(empName, fontName, colorBrush, new Point(80, 120));
e.Graphics.DrawString(empPosition, fontPosition, colorBrush, new Point(80, 140));
e.Graphics.DrawString(empId, fontPosition, colorBrush, new Point(680, 120));
DataManipulation.PrintSelectEmployeeByMonth(i, e, comboBoxMonth, comboBoxYear, comboBoxDayFrom, comboBoxDayTo);
countPage++;
MessageBox.Show(countPage.ToString());
}
if (countPage <= countEmployee)
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The PrintPage event is raised once for each page; your for loop suggests that you are trying to print all the pages whenever the event is raised.
You need to remove the for loop and promote the index variable i to an instance-level variable that you can use to track the current page number.
The remainder of your code appears to be correct; you must keep requesting more pages until the event has been fired countEmployee times.
Related
Basically i got a form with a panel inside of it 2 buttons one called newClient , once the user clicks on it the Click_event kicks in (check the code ) !
I have tried to dispose cntrols inside of the panel but still nothing !
private void newClient_Click(object sender, EventArgs e)
{
MainPanel.Dispose();
this.Height += 300;
this.CenterToScreen();
string[] txtBoxNames = new string[] { "fullName", "cinRef", "mainAddr", "phoneNbr","gender","birthDate" };
try
{
for (int i = 0; i < 4; i++)
{
TextBox tb = new TextBox();
tb.Name = txtBoxNames[i];
tb.Location = new Point(20, 150);
this.Controls.Add(tb);
}
}
catch (Exception ex )
{
MessageBox.Show(ex.Message);
}
}
In brief, what i'm trying to achieve here is to add some dynamic Controls to the form !
I am printing a panel with all its controls Inside. My problem is that I want to make a counter Inside this panel and increase its value for each pages printed. I tried incrementing the counter Inside my PrintPage event but this isn't working. Would it be possible to add multiple printpage events with increased counter for every page ? Here's my not working code. Thanks for giving me advices about how I could do this printing...
private void PrintPage(object o, PrintPageEventArgs e)
{
try
{
if (File.Exists(toPrint) && nbrPrint < nbrPages)
{
Rectangle m = panel1.ClientRectangle;
Bitmap imaag = new Bitmap(m.Width, m.Height);
panel1.DrawToBitmap(imaag, m);
e.Graphics.DrawImage(imaag, e.MarginBounds);
nbrPrint++;
compteurPrint++;
cpt.Text = compteurPrint.ToString();
}
}
catch (Exception)
{
}
}
nbrPrint is the pages printed, nbrPages the number of pages asked to print, compteurPrint the value I need to print in the page (which needs to be incremented), cpt is the label (Inside panel1) in which I show compteurPrint.
Since I do this:
pd.PrintPage += PrintPage;
pd.Print();
Can I do:
while (nbrPrint < nbrPages)
{
pd.PrintPage += PrintPage;
compteurPrint++;
}
pd.Print();
I think it would be the same result as what I'm currently doing…
Thanks for help !
You need to set the HasMorePages property on PrintPageEventArgs to tell it that there are more pages to print.
private void PrintPage(object sender, PrintPageEventArgs e)
{
try
{
if (File.Exists(toPrint) && nbrPrint < nbrPages)
{
Rectangle m = panel1.ClientRectangle;
Bitmap imaag = new Bitmap(m.Width, m.Height);
panel1.DrawToBitmap(imaag, m);
e.Graphics.DrawImage(imaag, e.MarginBounds);
nbrPrint++;
compteurPrint++;
cpt.Text = compteurPrint.ToString();
e.HasMorePages = true; // Set this to true as long as there are more pages to print. It defaults to false.
}
}
catch (Exception)
{
}
}
Checkout the Microsoft documentation for an example: PrintDocument.PrintPage
I'm trying to print a very long string using code below but it prints the whole text only in one page. Is there any easy way to print it correctly?
string text="the text has like 1000 words";
System.Drawing.Printing.PrintDocument p = new System.Drawing.Printing.PrintDocument();
p.PrintPage += delegate (object sender1, System.Drawing.Printing.PrintPageEventArgs e1)
{
e1.Graphics.DrawString(text, new System.Drawing.Font("Times New Roman", 12), new System.Drawing.SolidBrush(System.Drawing.Color.Black), new System.Drawing.RectangleF(50, 50, p.DefaultPageSettings.PrintableArea.Width - 50, p.DefaultPageSettings.PrintableArea.Height - 50));
};
try
{
p.Print();
}
catch (Exception ex)
{
throw new Exception("Exception Occured While Printing", ex);
}
I tried to solve it with this article but the method stuck in some loop that I don't know how to fix.
You have to keep in mind that PrintDocument will raise the event PrintPage as long as you tell it there are more pages. It is your task to keep track of what is printed, what needs to printed next and if you need another page or not.
There are several ways to accomplish that. I have chosen in this case to take the content of your text, check how much of it fits on the current page, DrawString that bit and then update my processing string, called remainingtext to be able to repeat for the next Page. The decision if a next page is needed is controlled by setting HasMorepages of the PrintEvent arguments instance to true or false when we're done.
Here is the code:
PrintDocument p = new PrintDocument();
var font = new Font("Times New Roman", 12);
var margins = p.DefaultPageSettings.Margins;
var layoutArea = new RectangleF(
margins.Left,
margins.Top,
p.DefaultPageSettings.PrintableArea.Width - (margins.Left + margins.Right ),
p.DefaultPageSettings.PrintableArea.Height - (margins.Top + margins.Bottom));
var layoutSize = layoutArea.Size;
layoutSize.Height = layoutSize.Height - font.GetHeight(); // keep lastline visible
var brush = new SolidBrush(Color.Black);
// what still needs to be printed
var remainingText = text;
p.PrintPage += delegate (object sender1, PrintPageEventArgs e1)
{
int charsFitted, linesFilled;
// measure how many characters will fit of the remaining text
var realsize = e1.Graphics.MeasureString(
remainingText,
font,
layoutSize,
StringFormat.GenericDefault,
out charsFitted, // this will return what we need
out linesFilled);
// take from the remainingText what we're going to print on this page
var fitsOnPage = remainingText.Substring(0, charsFitted);
// keep what is not printed on this page
remainingText = remainingText.Substring(charsFitted).Trim();
// print what fits on the page
e1.Graphics.DrawString(
fitsOnPage,
font,
brush,
layoutArea);
// if there is still text left, tell the PrintDocument it needs to call
// PrintPage again.
e1.HasMorePages = remainingText.Length > 0;
};
p.Print();
When I hookup an PrintPreviewControl this is the result:
So thanks to rene I figured it out how to print it correctly. I edit his code and the difference here is that the user chooses the paper size and rectangel drawing happens with choosen paper margin size. This is a ready printing method in case you want to use it...
private void Print(string thetext){
try
{
System.Drawing.Printing.PrintDocument p = new System.Drawing.Printing.PrintDocument();
var font = new Font("Times New Roman", 12);
var brush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
// what still needs to be printed
var remainingText = theText;
p.PrintPage += delegate (object sender1, System.Drawing.Printing.PrintPageEventArgs e1)
{
int charsFitted, linesFilled;
// measure how many characters will fit of the remaining text
var realsize = e1.Graphics.MeasureString(
remainingText,
font,
e1.MarginBounds.Size,
System.Drawing.StringFormat.GenericDefault,
out charsFitted, // this will return what we need
out linesFilled);
// take from the remainingText what we're going to print on this page
var fitsOnPage = remainingText.Substring(0, charsFitted);
// keep what is not printed on this page
remainingText = remainingText.Substring(charsFitted).Trim();
// print what fits on the page
e1.Graphics.DrawString(
fitsOnPage,
font,
brush,
e1.MarginBounds);
// if there is still text left, tell the PrintDocument it needs to call
// PrintPage again.
e1.HasMorePages = remainingText.Length > 0;
};
System.Windows.Forms.PrintDialog pd = new System.Windows.Forms.PrintDialog();
pd.Document = p;
DialogResult result = pd.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
p.Print();
}
}catch(Exception e2)
{
System.Windows.MessageBox.Show(e2.Message, "Unable to print",MessageBoxButton.OK);
}
}
Code snippet for "when user clicked 'btnPrint' button, print 'rtbEditor' rich textbox's text.":
private void btnPrint_Click(object sender, EventArgs e) {
var d = new PrintDialog();
d.Document = new PrintDocument();
d.Document.PrintPage += Dd_PrintPage;
remainingText = rtbEditor.Text;
var res = d.ShowDialog();
try { if (res == DialogResult.OK) d.Document.Print(); }
catch { }
}
string remainingText;
private void Dd_PrintPage(object sender, PrintPageEventArgs e){
//this code was for 1 page
//e.Graphics.DrawString(rtbEditor.Text,new Font("Comic Sans MS", 12f),Brushes.Black,new PointF(10,10));
//this is for multiple pages
PrintDocument p = ((PrintDocument)sender);
var font = new Font("Times New Roman", 12);
var margins = p.DefaultPageSettings.Margins;
var layoutArea = new RectangleF(
margins.Left,
margins.Top,
p.DefaultPageSettings.PrintableArea.Width - (margins.Left + margins.Right),
p.DefaultPageSettings.PrintableArea.Height - (margins.Top + margins.Bottom));
var layoutSize = layoutArea.Size;
layoutSize.Height = layoutSize.Height - font.GetHeight(); // keep lastline visible
var brush = new SolidBrush(Color.Black);
int charsFitted, linesFilled;
// measure how many characters will fit of the remaining text
var realsize = e.Graphics.MeasureString(
remainingText,
font,
layoutSize,
StringFormat.GenericDefault,
out charsFitted, // this will return what we need
out linesFilled);
// take from the remainingText what we're going to print on this page
var fitsOnPage = remainingText.Substring(0, charsFitted);
// keep what is not printed on this page
remainingText = remainingText.Substring(charsFitted).Trim();
// print what fits on the page
e.Graphics.DrawString(
fitsOnPage,
font,
brush,
layoutArea);
// if there is still text left, tell the PrintDocument it needs to call
// PrintPage again.
e.HasMorePages = remainingText.Length > 0;
}
I am using the PrintDocument class to print to my Brother label printer. When I execute the Print() method, the printer starts flashing a red error light, but everything else returns successful.
I can run this same code on my laser printer and everything works fine.
How can I see what is causing the error on my label printer?
Code:
public class Test
{
private Font printFont;
private List<string> _documentLinesToPrint = new List<string>();
public void Run()
{
_documentLinesToPrint.Add("Test1");
_documentLinesToPrint.Add("Test2");
printFont = new Font("Arial", 10);
var pd = new PrintDocument();
pd.DefaultPageSettings.Margins = new Margins(25, 25, 25, 25);
pd.DefaultPageSettings.PaperSize = new PaperSize("Label", 400, 237);
var printerSettings = new System.Drawing.Printing.PrinterSettings();
printerSettings.PrinterName ="Brother QL-570 LE";
pd.PrinterSettings = printerSettings;
pd.PrinterSettings.Copies = 1;
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
}
// The PrintPage event is raised for each page to be printed.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
float linesPerPage = 0;
float yPos = 0;
int count = 0;
float leftMargin = ev.MarginBounds.Left;
float topMargin = ev.MarginBounds.Top;
string line = null;
// Calculate the number of lines per page.
linesPerPage = ev.MarginBounds.Height /
printFont.GetHeight(ev.Graphics);
// Print each line of the file.
while ((count < linesPerPage) && (count < _documentLinesToPrint.Count))
{
line = _documentLinesToPrint[count];
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
line = null;
count++;
}
// If more lines exist, print another page.
if (line != null)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
}
}
PrintDocument is a very basic API. You get simple generic printing, but it comes at the cost of reduced functionality not specific to the print driver. My HP printer usually gives me a printed error rather than an Exception. Its not surprising to see something similar happening to you.
The blinking is likely a code that you can lookup. If that fails you can try saving to an Image format, PDF or XPS. Or use a 3rd party library or write your own PCL file. There's a ton of options. Creating an output you can view as opposed to one in memory should debugging calculations like margins. You can look at a PDF and see if it looks wacky. Just keep in mind the way it looks on the PC may be slightly different than the output especially when printing near the edges.
I could be completely wrong on this, but my understanding is that when you print with this code, it has nothing to do with the printer itself, but with the operating system. Windows sets up a print queue, places the output in it, and your code returns.
Then Windows takes items off of the queue and sends them through the printer driver and to your printer. If there's an error in printing, it should show up as a failed document in the print queue. I think it's too late to trap the error as an exception at this stage.
Please correct me if I am mistaken.
I would surround your the method bodies using a Try/Catch Block then handle the exception(s) within the catch of each method. As an example:
public class Test
{
private Font printFont;
private List<string> _documentLinesToPrint = new List<string>();
public void Run()
{
try
{
_documentLinesToPrint.Add("Test1");
_documentLinesToPrint.Add("Test2");
printFont = new Font("Arial", 10);
var pd = new PrintDocument();
pd.DefaultPageSettings.Margins = new Margins(25, 25, 25, 25);
pd.DefaultPageSettings.PaperSize = new PaperSize("Label", 400, 237);
var printerSettings = new System.Drawing.Printing.PrinterSettings();
printerSettings.PrinterName = "Brother QL-570 LE";
pd.PrinterSettings = printerSettings;
pd.PrinterSettings.Copies = 1;
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();
}
catch (InvalidPrinterException exc)
{
// handle your errors here.
}
catch (Exception ex)
{
// handle your errors here.
}
}
// The PrintPage event is raised for each page to be printed.
private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
try
{
float linesPerPage = 0;
float yPos = 0;
int count = 0;
float leftMargin = ev.MarginBounds.Left;
float topMargin = ev.MarginBounds.Top;
string line = null;
// Calculate the number of lines per page.
linesPerPage = ev.MarginBounds.Height /
printFont.GetHeight(ev.Graphics);
// Print each line of the file.
while ((count < linesPerPage) && (count < _documentLinesToPrint.Count))
{
line = _documentLinesToPrint[count];
yPos = topMargin + (count *
printFont.GetHeight(ev.Graphics));
ev.Graphics.DrawString(line, printFont, Brushes.Black,
leftMargin, yPos, new StringFormat());
line = null;
count++;
}
// If more lines exist, print another page.
if (line != null)
ev.HasMorePages = true;
else
ev.HasMorePages = false;
}
catch (InvalidPrinterException exc)
{
// handle your errors here.
}
catch (Exception ex)
{
// handle your errors here.
}
}
}
I am trying to print a multidimensional tiff. This tiff is having 3 Pages using variable imagetoprint. So I wrote following code, that unfortunately only prints the first dimension. All others are printed on empty paper. If I save the image from memory to file, irfanview shows all pages correctly...
Who can give me a hint ?
public void print(Bitmap imageToPrint, string printerName, int pagesToPrint)
{
try
{
printmap = imageToPrint;
cur_page = 0;
max_pages = pagesToPrint;
m.Top = 1 * dpi; // Set a 1' margin, from the top
m.Left = 1.25f * dpi; // Set a 1.25' margin, from the left
m.Bottom = printmap.Height - m.Top; // 1', from the bottom
m.Right = printmap.Width; // rechter Rand so weit wie es eben geht
m.Width = printmap.Width - (m.Left * 2); // Get the width of our working area
m.Height = printmap.Height - (m.Top * 2); // Get the height of our working area
pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);
if (printerName != "")
pd.DefaultPageSettings.PrinterSettings.PrinterName = printerName;
pd.DefaultPageSettings.Color = true;
pd.DefaultPageSettings.PrinterSettings.PrintFileName = "tiffprint";
pd.DocumentName = "InstantFormsPrinting";
if (m.Width > m.Height)
{
pd.DefaultPageSettings.Landscape = true;
}
pd.Print(); // Print
}
catch (Exception ex)
{
Console.WriteLine("Error during print preparation:" + ex.Message);
}
}
// Our printing event
public void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Rectangle crop = new Rectangle(1, 1, 200, 200);
try
{
printmap.SelectActiveFrame(FrameDimension.Page, cur_page);
e.Graphics.DrawImageUnscaled(printmap, new Point(0, 0));
++cur_page;
e.HasMorePages = (cur_page < max_pages);
}
catch (Exception ex)
{
Console.WriteLine("Error during print operation:" + ex.Message);
}
}
On Page 2 pd_PrintPage thows an exception with "general gdi problem"
I have no idea so far. It would be very nice if somebody can help.
You could extract the pages into single bitmaps before you start printing.