I have the following code for my BeginPrint, PrintPage and Click event. Firing the click event, its printing all pages. I would like to add a print range on button event that prints from-to range:
BeginPrint:
private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
curRow = 0;
curCopy = 0;
if (printrange)
{
((PrintDocument)sender).PrinterSettings.PrintRange = PrintRange.SomePages;
((PrintDocument)sender).PrinterSettings.FromPage = 1;
((PrintDocument)sender).PrinterSettings.ToPage = 1;
printrange = false;
}
}
PrintPage : I'm generating QRCodes, borders and text in this method. Usually I have more than 2 pages with QRCodes. The problem is that it prints all pages
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
var curY = e.MarginBounds.Y;
var curX = e.MarginBounds.X 30;// 10
Pen pen = new Pen(System.Drawing.ColorTranslator.FromHtml("#FFBD2D"), 1);
using (var fontNormal = new Font("Arial", 10))
using (var sf = new StringFormat())
{
sf.Alignment = sf.LineAlignment = StringAlignment.Center;
int itemHeight = (int)fontNormal.GetHeight(e.Graphics);
for (int row = curRow; row < dt.Rows.Count; row )
{
DataRow dr = dt.Rows[row];
if (!string.IsNullOrEmpty(dr.Field<string>(1)) &&
int.TryParse(dr.Field<string>(4)?.ToString(), out int copies))
{
for (int i = curCopy; i < copies; i )
{
var imgRect = new Rectangle(curX, curY, 156, 156);//e.MarginBounds.X
var labelRect = new Rectangle(
imgRect.X 180 20,//eltol
imgRect.Bottom-162,
itemHeight,
imgRect.Width);
using (var qrImage = GenerateQRCODE(dr[1].ToString()))
{
e.Graphics.DrawImage(RotateImage(qrImage, -90), imgRect);
}
SizeF labelSize = e.Graphics.MeasureString(dr[1].ToString(), fontNormal);
Bitmap stringmap = new Bitmap((int)labelSize.Height 1, (int)labelSize.Width 1);
Graphics gbitmap = Graphics.FromImage(stringmap);
gbitmap.TranslateTransform(0, labelSize.Width);
gbitmap.RotateTransform(-90);
gbitmap.DrawString(dr[1].ToString(), fontNormal, Brushes.Black, new PointF(0, 0), new StringFormat());
e.Graphics.DrawImage(stringmap, labelRect);
gbitmap.Dispose();
stringmap.Dispose();
e.Graphics.DrawLine(pen, curX, curY, curX, curY 156);//57 |<
e.Graphics.DrawLine(pen, curX, curY 156 , curX 156 220, curY 156);// _
e.Graphics.DrawLine(pen, curX 156 220, curY 156, curX 156 220, curY);// >|
e.Graphics.DrawLine(pen, curX, curY, curX 156 220, curY);// -
curX = imgRect.Right 230; //horizontal gap
if (curX imgRect.Width > e.MarginBounds.Right)
{
curX = e.MarginBounds.X 30;
curY = labelRect.Bottom 30;//55vertical gap
}
if (curY imgRect.Height >= e.MarginBounds.Bottom)
{
curCopy = i 1;
e.HasMorePages = true;
return;
}
}
}
curRow = row 1;
curCopy = 0;
}
}
refreshprintbtn.Enabled = true;
printdialogbtn.Enabled = true;
}
In this click event I'm calling the print() method:
bool printrange = false;
private void printrangebtn_Click(object sender, EventArgs e)
{
printrange = true;
printDocument1.BeginPrint = printDocument1_BeginPrint;
printDocument1.PrintPage = printDocument1_PrintPage;
printDocument1.Print();
}
Thanks
CodePudding user response:
You forgot to implement the PrintRange
part in the PrintPage
event. Just setting the PrintRange
, FromPage
, and ToPage
properties doesn't mean that the printer knows which page should start with and which one should be the last. These properties exist to get the user inputs through the print dialogs or some setter methods and you need to use them as factors in your implementation.
For example, in PrintRange.SomePages
case, use a class field to determine the target pages to print. Increment the field and print only if the value is within the .From
and .To
range.
//
System.Drawing;
using System.Drawing.Printing;
// ...
private int curRow, curCopy, curPage;
public YourForm()
{
InitializeComponent();
printDocument1.BeginPrint = printDocument1_BeginPrint;
printDocument1.PrintPage = printDocument1_PrintPage;
}
private void printrangebtn_Click(object sender, EventArgs e)
{
printDocument1.PrinterSettings.PrintRange = PrintRange.SomePages;
printDocument1.PrinterSettings.FromPage = 1;
printDocument1.PrinterSettings.ToPage = 2;
printDocument1.Print();
}
private void printDocument1_BeginPrint(object sender, PrintEventArgs e)
{
curRow = 0;
curCopy = 0;
curPage = 0;
// ...
}
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
var curY = e.MarginBounds.Y;
var curX = e.MarginBounds.X 30;// 10
var doc = sender as PrintDocument;
using (var pen = new Pen(ColorTranslator.FromHtml("#FFBD2D")))
using (var fontNormal = new Font("Arial", 10))
using (var sf = new StringFormat())
{
sf.Alignment = sf.LineAlignment = StringAlignment.Center;
int itemHeight = (int)fontNormal.GetHeight(e.Graphics);
for (int row = curRow; row < dt.Rows.Count; row )
{
curPage ;
var doPrint = doc.PrinterSettings.PrintRange != PrintRange.SomePages ||
(curPage >= doc.PrinterSettings.FromPage && curPage <= doc.PrinterSettings.ToPage);
DataRow dr = dt.Rows[row];
if (!string.IsNullOrEmpty(dr.Field<string>(1)) &&
int.TryParse(dr.Field<string>(4)?.ToString(), out int copies))
{
for (int i = curCopy; i < copies; i )
{
var imgRect = new Rectangle(curX, curY, 156, 156);//e.MarginBounds.X
var labelRect = new Rectangle(
imgRect.X 180 20,//eltol
imgRect.Bottom - 162,
itemHeight,
imgRect.Width);
// If not, don't print and continue the calculations...
if (doPrint)
{
using (var qrImage = GenerateQRCODE(dr[1].ToString()))
e.Graphics.DrawImage(RotateImage(qrImage, -90), imgRect);
SizeF labelSize = e.Graphics.MeasureString(dr[1].ToString(), fontNormal);
Bitmap stringmap = new Bitmap((int)labelSize.Height 1, (int)labelSize.Width 1);
Graphics gbitmap = Graphics.FromImage(stringmap);
gbitmap.TranslateTransform(0, labelSize.Width);
gbitmap.RotateTransform(-90);
gbitmap.DrawString(dr[1].ToString(), fontNormal, Brushes.Black, new PointF(0, 0), new StringFormat());
e.Graphics.DrawImage(stringmap, labelRect);
gbitmap.Dispose();
stringmap.Dispose();
e.Graphics.DrawLine(pen, curX, curY, curX, curY 156);//57 |<
e.Graphics.DrawLine(pen, curX, curY 156, curX 156 220, curY 156);// _
e.Graphics.DrawLine(pen, curX 156 220, curY 156, curX 156 220, curY);// >|
e.Graphics.DrawLine(pen, curX, curY, curX 156 220, curY);// -
}
curX = imgRect.Right 230; //horizontal gap
if (curX imgRect.Width > e.MarginBounds.Right)
{
curX = e.MarginBounds.X 30;
curY = labelRect.Bottom 30;//55vertical gap
}
if (curY imgRect.Height >= e.MarginBounds.Bottom)
{
if (!doPrint) break;
curCopy = i 1;
e.HasMorePages = true;
return;
}
}
}
if (!doPrint)
{
curX = e.MarginBounds.X;
curY = e.MarginBounds.Y;
}
curRow = row 1;
curCopy = 0;
}
}
refreshprintbtn.Enabled = true;
printdialogbtn.Enabled = true;
}
Side Notes
- You shouldn't add handlers for the
PrintDocument
events each time you click a Button unless you remove the current handlers first in theEndPrint
for example. Just add them once as shown in the Form's ctor orLoad
event. System.Drawing.Pen
is a disposable object so you need to dispose of it as well. Create it with theusing
statement or pass an instanceusing (pen) ...
or call the.Dispose();
method explicitly. Do the same for any object implements theIDisposable
interface.