Thats my printpage Event Handler Code
private void printDocument2_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int yaxis = 0;
Font font = new Font("Arial", 12, FontStyle.Bold);
for (int i = 0; i < 300; i++)
{
e.Graphics.DrawString("Store Inventory Report", font, Brushes.Black, 0, yaxis);
yaxis += 30;
}
}
This code only prints line 37 times. . . its not printing full page. . i generates its pdf, pdf also have line 37 times.
With full printing did you mean printing all the 300 lines base on your code? If it is you should set the parameter:
e.HasMorePages = true;
Set it to false when you reach the condition where all contents are already printed.
For your case it would be something like this:
private int startIndex = 0; //Keeps track of printed index
private int limit = 300; //Limit of items to print
private void printDocument2_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int yaxis = 0;
Font font = new Font("Arial", 12, FontStyle.Bold);
for (int i = startIndex; i < limit; i++)
{
e.Graphics.DrawString("Store Inventory Report", font, Brushes.Black, 0, yaxis);
yaxis += 30;
//Reaches bottom? break the loop
if (yaxis > e.PageBounds.Bottom)
{
startIndex = i + 1; //Set to next page's data index
break;
}
}
//Still has pages?
e.HasMorePages = startIndex < limit;
}
Related
using C#, I wrote the below code to print out images in an array (size = totalToPrint) of Picturebox pictureBoxArr[] each in size of 100x100 pixel. I want to print them vertically with the 20-pixel distance between them heightDistanceBetweenImages the problem is that it only prints on 1 page (say letter size) no matter how many images ( then it only prints 8 images and dismisses the rest). How can I solve this problem, and print it on multiple pages?
int totalToPrint;
int xFirstAncorPoint = 100;
int yFirstAncorPoint = 100;
int ImagSize = 100; // Squre of 100x100 pixel
int heightDistanceBetweenImages = 20;
PrintDialog pd = new PrintDialog();
PrintDocument pDoc = new PrintDocument();
pDoc.PrintPage += PrintPicture;
pd.Document = pDoc;
if (pd.ShowDialog() == DialogResult.OK)
{
pDoc.Print();
}
}
public void PrintPicture(Object sender, PrintPageEventArgs e)
{
Bitmap bmp1 = new Bitmap(ImagSize , totalToPrint * (ImagSize + heightDistanceBetweenImages));
for (int i = 0; i < totalToPrint; i++)
{
pictureBoxArr[i].DrawToBitmap(bmp1, new Rectangle(0, i * (heightDistanceBetweenImages + ImagSize), pictureBoxArr[0].Width, pictureBoxArr[0].Height));
}
e.Graphics.DrawImage(bmp1, xFirstAncorPoint, yFirstAncorPoint);
bmp1.Dispose();
}
You are about half way there. PrintDocument would be your future reference.
The PrintPage gives you more than just a drawing space; it also has your page bounds, page margins, etc. It also has HasMorePages property that you set if you need to print more pages. This property defaults to false, so you were only printing 1 page. Also if anything is outside the bounds of the page, it would not print that. With a little change here and there, you would end up with something like this.
// using queue to manage images to print
Queue<Image> printImages = new Queue<Image>();
int totalToPrint;
int xFirstAncorPoint = 100;
int yFirstAncorPoint = 100;
int ImagSize = 100; // Squre of 100x100 pixel
int heightDistanceBetweenImages = 20;
private void btnPrintTest_Click(object sender, EventArgs e) {
PrintDialog pd = new PrintDialog();
PrintDocument pDoc = new PrintDocument();
pDoc.PrintPage += PrintPicture;
pd.Document = pDoc;
if (pd.ShowDialog() == DialogResult.OK) {
// add image references to printImages queue.
for (int i = 0; i < pictureBoxArr.Length; i++) {
printImages.Enqueue(pictureBoxArr[i].Image);
}
pDoc.Print();
}
}
private void PrintPicture(object sender, PrintPageEventArgs e) {
int boundsHeight = e.MarginBounds.Height; // Get height of bounds that we are expected to print in.
int currentHeight = yFirstAncorPoint;
while (currentHeight <= boundsHeight && printImages.Count > 0) {
var nextImg = printImages.Peek();
int nextElementHeight = nextImg.Height + heightDistanceBetweenImages;
if (nextElementHeight + currentHeight <= boundsHeight) {
e.Graphics.DrawImage(nextImg, new PointF(xFirstAncorPoint, currentHeight + heightDistanceBetweenImages));
printImages.Dequeue();
}
currentHeight += nextElementHeight;
}
// how we specify if we may have more pages to print
e.HasMorePages = printImages.Count > 0;
}
Hopefully this gets you on the right path and with some minor tweaks for your code, you will have what you need.
I've got the following code, and looked at as many similar questions on here and google, but all solutions have the same flaw, when the content in the RTB is longer than one page, or more than one or two lines, it prints an infinite number of pages. What should be changed to only print the correct number of pages?
private void PrintButton_Click(object sender, EventArgs e)
{
if (MainTabSet.TabCount > 0)
{
RichTextBox textbox = (RichTextBox)MainTabSet.SelectedTab.Controls["TabTextBox"];
PrintDocument docToPrint = new PrintDocument();
docToPrint.PrintPage += new PrintPageEventHandler(PrintPageHandler);
docToPrint.DocumentName = MainTabSet.SelectedTab.Text;
PrintDialog.Document = docToPrint;
if(PrintDialog.ShowDialog() == DialogResult.OK)
{
docToPrint.Print();
}
}
}
private void PrintPageHandler(object sender, PrintPageEventArgs e)
{
if (MainTabSet.TabCount > 0)
{
RichTextBox textbox = (RichTextBox)MainTabSet.SelectedTab.Controls["TabTextBox"];
StringReader reader = new StringReader(textbox.Text);
float linesPerPage = 0.0f;
float yPosition = 0.0f;
int count = 0;
float leftMargin = e.MarginBounds.Left;
float rightMargin = e.MarginBounds.Right;
float topMargin = e.MarginBounds.Top;
string line = null;
Font printFont = textbox.Font; //maybe do selection font
SolidBrush printBrush = new SolidBrush(textbox.ForeColor);//Maybe do selection color
int charPos = 0;
int xPosition = (int)leftMargin;
linesPerPage = e.MarginBounds.Height / printFont.GetHeight(e.Graphics);
while (count < linesPerPage && ((line = reader.ReadLine()) != null))
{
xPosition = (int)leftMargin;
yPosition = topMargin + (count * printFont.GetHeight(e.Graphics));
count++;
for (int i = 0; i < line.Length; i++)
{
textbox.Select(charPos, 1);
if ((xPosition + ((int)e.Graphics.MeasureString(textbox.SelectedText, textbox.SelectionFont).Width)) > rightMargin)
{
count++;
if (!(count < linesPerPage))
{
break;
}
xPosition = (int)leftMargin;
yPosition = topMargin + (count * printFont.GetHeight(e.Graphics));
}
printBrush = new SolidBrush(textbox.SelectionColor);
e.Graphics.DrawString(textbox.SelectedText, textbox.SelectionFont, printBrush, new PointF(xPosition, yPosition));
xPosition += ((int)e.Graphics.MeasureString(textbox.SelectedText, textbox.SelectionFont).Width);
charPos++;
}
}
if (line != null)
{
e.HasMorePages = true;
}
else
{
e.HasMorePages = false;
printBrush.Dispose();
}
}
}
Thanks in advance for the help.
//Nodnarb3
Add this code in PrintPageHandler
private void PrintPageHandler(object sender, PrintPageEventArgs e)
{
int charactersOnPage = 0;
int linesPerPage = 0;
// Sets the value of charactersOnPage to the number of characters
// of stringToPrint that will fit within the bounds of the page.
e.Graphics.MeasureString(stringToPrint, font1,
e.MarginBounds.Size, StringFormat.GenericTypographic,
out charactersOnPage, out linesPerPage);
// Draws the string within the bounds of the page
e.Graphics.DrawString(stringToPrint, font1, Brushes.Black,
e.MarginBounds, StringFormat.GenericTypographic);
// Remove the portion of the string that has been printed.
stringToPrint = stringToPrint.Substring(charactersOnPage);
// Check to see if more pages are to be printed.
e.HasMorePages = (stringToPrint.Length > 0);
}
And the PrintButton Code
private void PrintButton_Click(object sender, EventArgs e)
{
stringToPrint = tabsProperties[tabsProperties.IndexOf(new TabProperties(this.tabControl1.SelectedIndex))].TabHtml;
printDialog1.ShowDialog();
printDocument1.Print();
}
This question already has answers here:
How to print values from a DataGridView control
(3 answers)
Closed 8 years ago.
i want to print entire rows of an DGV.
this should be done by extracting the values not taking picture...(if you don't understand please comment below)
is there any way i can do this?
Still facing problem...
https://drive.google.com/file/d/0BxqCNfHpYEJlUVg3VW5aZlpHMlk/view?usp=sharing
Here is an absolutely minimal code example.
It prints all rows of a dgv, including simple headers and footers..
You need to add a PrintDocument printDocument1 to your form.
Also a Button cb_printPreview.
// a few variables to keep track of things across pages:
int nextPageToPrint = -1;
int linesOnPage = -1;
int linesPrinted = -1;
int maxLinesOnPage = -1;
private void printDocument1_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
// for each fresh page:
linesOnPage = 0;
nextPageToPrint++;
// a short reference to the DataGridView we want to print
DataGridView DGV = yourDataGridView;
// I prefer mm, pick your own unit!
e.Graphics.PageUnit = GraphicsUnit.Millimeter;
// I want to print the columns at these fixed positions
// the first one is the left margin,
// the last one a dummy at the right page margin
int[] tabStops = new int[4] {15, 30, 100, 190};
// I want only one column to be right-aligned:
List<int> rightAlignedCols = new List<int>() { 1 };
// we need to keep track of the horizontal position
// this is also the top margin:
float y = 35f;
// we add a little space between the lines:
float leading = 1.5f;
// we will need to measure the texts we print:
SizeF size = Size.Empty;
// we use only one font:
using (Font font = new Font("Consolas", 13f))
{
// a simple header:
e.Graphics.DrawString("List " + printDocument1.DocumentName,
font, Brushes.Black, 50, y);
y += size.Height + 15;
// I loop over the all rows:
for (int row = linesPrinted; row < DGV.Rows.Count; row++)
{
// I print a light gray bar over every second line:
if (row % 2 == 0)
e.Graphics.FillRectangle(Brushes.Gainsboro,
tabStops[0], y - leading / 2, e.PageBounds.Width - 25, size.Height);
// I print all (3) columns in black, unless they're empty:
for (int col = 0; col < DGV.ColumnCount; col++)
if (DGV[0, row].Value != null)
{
string text = DGV[col, row].FormattedValue.ToString();
size = e.Graphics.MeasureString(text, font, 9999);
float x = tabStops[col];
if (rightAlignedCols.Contains(col) )
x = tabStops[col + 1] - size.Width;
// finally we print an item:
e.Graphics.DrawString(text, font, Brushes.Black, x, y);
}
// advance to next line:
y += size.Height + leading;
linesOnPage++;
linesPrinted++;
if (linesOnPage > maxLinesOnPage) // page is full
{
e.HasMorePages = true; // more to come
break; // leave the rows loop!
}
}
e.Graphics.DrawString("Page " + nextPageToPrint, font,
Brushes.Black, tabStops[3] -20, y + 15);
}
}
private void cb_printPreview_Click(object sender, EventArgs e)
{
PrintPreviewDialog PPVdlg = new PrintPreviewDialog();
PPVdlg.Document = printDocument1;
PPVdlg.ShowDialog();
}
private void printDocument1_BeginPrint(object sender,
System.Drawing.Printing.PrintEventArgs e)
{
// create a demo title for the page header:
printDocument1.DocumentName = " Suppliers as of "
+ DateTime.Now.ToShortDateString();
// initial values for a print job:
nextPageToPrint = 0;
linesOnPage = 0;
maxLinesOnPage = 30;
linesPrinted = 0;
}
The actual printing can be triggered from the PrintPreviewDialog.
There is also a PrintDialog and a PrintPreview control for more options.
Obviously one can add many more things, including graphics, multiple fonts etc, but this should give you an idea.. For full tutorials please look refer to the WWW & MSDN!
I have this list with 5 indices and I want to print the title on a new page, what do I write so it prints it on the next page?
list<> // 5 indices
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics graphic = e.Graphics;
float fontHeight = font.GetHeight();
int startX = 10;
int startY = 10;
for (int i = 0; i < list.Count; i++)
{
graphic.DrawString(list[i].Title, new Font("Courier New", 18), new SolidBrush(Color.Black), startX, startY);
}
}
You have to maintain an instance variable which points to the current index of the item in the list to display , and increment it every time a page is printed.
int currIndex = 0;
void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics graphic = e.Graphics;
float fontHeight = font.GetHeight();
int startX = 10;
int startY = 10;
graphic.DrawString(list[currIndex++].Title, new Font("Courier New", 18), new SolidBrush(Color.Black), startX, startY);
if(currIndex == list.Count)
{
e.HasMorePages = false;
currIndex = 0;
}
else
{
e.HasMorePages = true;
}
}
The printDocument object calls that same PrintPage() method for every page. If you want different content to appear on different pages, you need code that lives outside of that method to store the current state, and code within the method to check that state and resume/continue printing based on the state you stored outside of the method.
If you have instructions in the PrintPage() to print the title, then the title will be printed. End of story.
I am attempting to print something using a C# Winforms application. I can't seem to understand how multiple pages works. Let's say I have the following code in my constructor:
private string _stringToPrint;
_stringToPrint = "";
for (int i = 0; i < 120; i++)
{
_stringToPrint = _stringToPrint + "Line " + i.ToString() + Environment.NewLine;
}
Then I have this code on my button click event:
private void MnuFilePrintClick(object sender, EventArgs e)
{
var pd = new PrintDocument();
pd.PrintPage += pd_PrintPage;
var z = new PrintPreviewDialog { Document = pd };
z.ShowDialog(this);
}
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
Graphics g = e.Graphics;
var font = new Font("Arial", 10f, FontStyle.Regular);
g.DrawString(_stringToPrint, font, Brushes.Black, new PointF(10f, 10f));
}
Right now, when I run this code, it is giving me one page and after like 70 lines, it just runs off the paper. How would I print this string so that it prints enough for one page, then runs over to the second page, etc..?
You could have a counter and set the amount of lines you want per page like so:
private string[] _stringToPrint = new string[100]; // 100 is the amount of lines
private int counter = 0;
private int amtleft = _stringToPrint.Length;
private int amtperpage = 40; // The amount of lines per page
for (int i = 0; i < 120; i++)
{
_stringToPrint[i] ="Line " + i.ToString();
}
Then in pd_PrintPage:
void pd_PrintPage(object sender, PrintPageEventArgs e)
{
int currentamt = (amtleft > 40)?40:amtleft;
Graphics g = e.Graphics;
var font = new Font("Arial", 10f, FontStyle.Regular);
for(int x = counter; x < (currentamt+counter); x++)
{
g.DrawString(_stringToPrint[x], font, Brushes.Black, new PointF(10f, (float)x*10));
// x*10 is just so the lines are printed downwards and not on top of each other
// For example Line 2 would be printed below Line 1 etc
}
counter+=currentamt;
amtleft-=currentamt;
if(amtleft<0)
e.HasMorePages = true;
else
e.HasMorePages = false;
// If e.HasMorePages is set to true and the 'PrintPage' has finished, it will print another page, else it wont
}
I have had bad experiences with e.HasMorePages so this may not work.
Let me know if this works and I hope it helps!