问题描述
我必须为我们公司生产的产品打印运输标签.
I have to print shipping labels for the products our company manufactures.
为了让自己了解这些标签的效果,我使用 Windows 窗体设计它们.这允许我使用 Label
控件定位文本、正确设置字体等,添加自定义 BarCode
控件,并获得fancy" 使用 Panel
控件将项目分组到框中.
To help give myself a feel for how these labels will turn out, I design them using a Windows Form. This allows me to position my text, get the fonts set right, etc. using Label
controls, add a custom BarCode
control, and get "fancy" with Panel
controls to group items into boxes.
每页包含两 (2) 个标签.
Each page holds two (2) labels.
当我的代码打印标签文档时,我要求打印 2、4 或 6 份副本.有时,也会使用打印预览.在这种情况下,我必须重置创建的标签数量.
When my code prints a label document, I request either 2, 4 or 6 copies. Occasionally, the Print Preview is used as well. In this case, I have to reset the number of labels created.
但是,当文档打印时:
- 如果请求是 2 份,代码将打印 2 张纸(4 个标签)
- 如果请求是 4 份,代码将打印 8 张纸(16 个标签)
- 如果请求是 6 份,代码会打印多达 18 页(36 个标签)
有人看到模式了吗?我没有.
Does anyone see a pattern? I do not.
这是我的打印命令:
public int Print(string docName, int rows, int columns, int copies) {
short shortCopies = (short)copies;
LabelsHorizontal = rows;
LabelsVertical = columns;
Size docSize = PrintPreview.Document.DefaultPageSettings.Bounds.Size;
float height = 0.8F * Screen.PrimaryScreen.WorkingArea.Size.Height;
float width = (height * docSize.Width) / docSize.Height;
Size winSize = new Size((int)width, (int)height);
PrintPreview.Height = winSize.Height;
PrintPreview.Width = winSize.Width;
if (!String.IsNullOrEmpty(docName)) {
PrintPreview.Document.DocumentName = docName;
}
PrintPreview.Document.PrinterSettings.Copies = shortCopies;
PrintPreview.SettingsFilename = Settings.PageSettingsLocation;
if (!PrintPreview.PrinterSelected) {
if (PrintPreview.ShowPrinterSelectDialog() != DialogResult.OK) {
return 0;
}
}
labelQtyPrinted = 0;
if (ShowPrintPreview) {
PrintPreview.ShowDialog();
} else {
PrintPreview.PrintDocument();
}
return labelQtyPrinted;
}
// Resets the Label Count between PrintPreview and Print
private void PrintPreview_OnPrintClicked(object sender, EventArgs e) {
labelQtyPrinted = 0;
}
我必须编写一个自定义 PrintPreview 类,该类将 PrintPreviewDialog
作为基类,以便我可以使用此 printButton_Click 方法覆盖其打印按钮:
I had to write a custom PrintPreview class that takes the PrintPreviewDialog
as a base class so that I could override its Print button with this printButton_Click method:
// Handles the Printing of the Document
internal void printButton_Click(object sender, EventArgs e) {
if (OnPrintClicked != null) {
OnPrintClicked(sender, e); // this resets my labelQtyPrinted value shown above
}
Document.Print();
printed = true;
Close();
}
在Print
方法(第一段代码)中,PrintPreview.PrintDocument()
只是调用printButton_Click
事件的代码.
In the Print
method (the first snippet of code), PrintPreview.PrintDocument()
is just code that calls the printButton_Click
event.
我的PrintPageEventHandler如下所示:
private void Document_Printed(object sender, PrintPageEventArgs e) {
if (PrintPreview.Document.PrinterSettings.Copies <= labelQtyPrinted) {
throw new Exception("Run Away Printer");
}
float scale;
SizeF pageSize = new SizeF(
PrintPreview.Document.DefaultPageSettings.PaperSize.Width,
PrintPreview.Document.DefaultPageSettings.PaperSize.Height
);
Margins m = PrintPreview.Document.DefaultPageSettings.Margins;
float printableHeight = pageSize.Height - (m.Top + m.Bottom);
float printableWidth = pageSize.Width - (m.Left + m.Right);
if (printableWidth < printableHeight) {
if (labelSize.Width < labelSize.Height) {
float r1 = (printableWidth) / labelSize.Width;
float r2 = (printableHeight) / labelSize.Height;
scale = (r1 < r2) ? r1 : r2;
} else {
scale = (printableWidth) / labelSize.Width;
}
} else {
if (labelSize.Width < labelSize.Height) {
scale = (printableHeight) / labelSize.Height;
} else {
float r1 = (printableWidth) / labelSize.Width;
float r2 = (printableHeight) / labelSize.Height;
scale = (r1 < r2) ? r1 : r2;
}
}
float lh = scale * labelSize.Height;
float lw = scale * labelSize.Width;
float ml = scale * m.Left;
float mt = scale * m.Top;
Graphics G = e.Graphics;
G.SmoothingMode = smoothMode;
G.TextRenderingHint = TextRenderingHint.AntiAlias;
for (int i = 0; i < LabelsHorizontal; i++) {
float dx = i * (lw + ml); // Horizontal shift * scale
for (int j = 0; j < LabelsVertical; j++) {
float dy = j * (lh + mt); // Vertical shift * scale
#region ' Panels '
foreach (Panel item in panels) {
float h = scale * item.Size.Height;
float w = scale * item.Size.Width;
float x = (ml + dx) + scale * item.Location.X;
float y = (mt + dy) + scale * item.Location.Y;
using (SolidBrush b = new SolidBrush(item.BackColor)) {
G.FillRectangle(b, x, y, w, h);
}
using (Pen p = new Pen(Brushes.Black)) {
G.DrawRectangle(p, x, y, w, h);
}
}
#endregion
#region ' Logo '
if (logo != null) {
float h = scale * logo.Height;
float w = scale * logo.Width;
float x = (ml + dx) + scale * logoPt.X;
float y = (mt + dy) + scale * logoPt.Y;
G.DrawImage(logo, x, y, w, h);
}
#endregion
#region ' Labels '
foreach (Label item in labels) {
float h = scale * item.Size.Height;
float w = scale * item.Size.Width;
float x = (ml + dx) + scale * item.Location.X;
float y = (mt + dy) + scale * item.Location.Y;
Color c = PrintPreview.Document.DefaultPageSettings.Color ? item.ForeColor : Color.Black;
Font font = new Font(item.Font.FontFamily, scale * item.Font.Size, item.Font.Style);
using (SolidBrush b = new SolidBrush(c)) {
StringFormat format = GetStringFormatFromContentAllignment(item.TextAlign);
format.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
format.Trimming = StringTrimming.None;
PointF locationF = new PointF(x, y);
SizeF size = new SizeF(w, h);
RectangleF r = new RectangleF(locationF, size);
G.DrawString(item.Text, font, b, r, format);
}
}
#endregion
#region ' Barcodes '
foreach (AcpBarcodeControl item in barcodes) {
Image img = item.GetBarcodeImage(item.BarcodeText);
if (img != null) {
float h = scale * item.Size.Height;
float w = scale * item.Size.Width;
float x = (ml + dx) + scale * item.Location.X;
float y = (mt + dy) + scale * item.Location.Y;
G.DrawImage(img, x, y, w, h);
}
}
#endregion
labelQtyPrinted++;
if (labelQtyPrinted == PrintPreview.Document.PrinterSettings.Copies) {
e.HasMorePages = false;
return;
}
}
e.HasMorePages = (labelQtyPrinted < PrintPreview.Document.PrinterSettings.Copies);
}
}
总而言之,它运作良好.Run Away Printer" 永远不会抛出异常.
All in all, it works very well. The "Run Away Printer" Exception is never thrown.
那么,为什么要制作这么多副本?
So, why are so many copies being made?
打印机是 HP LaserJet 4050(如果有区别的话).
The Printer is an HP LaserJet 4050, if that makes any difference.
推荐答案
我明白了!
Yippie!
好的,如果有人在意,事情就是这样:我需要每页打印两 (2) 个标签.
OK, if anyone cares, here's the deal: I needed to print two (2) labels per page.
我必须做的是计算要打印的页数,使用垂直和水平打印的标签数量.
What I had to do was calculate how many pages to print, using the number of labels to be printed vertically and horizontally.
我添加了变量 labelsRequested
并将现有变量 labelQtyPrinted
更改为 labelsPrinted
:
I added the variable labelsRequested
and changed the existing variable labelQtyPrinted
to be called labelsPrinted
:
private int labelsPrinted;
private int labelsRequested;
我的公共Print
方法改成这样:
My public Print
method was changed to this:
public int Print(string docName, int rows, int columns, int copies) {
LabelsHorizontal = rows;
LabelsVertical = columns;
if (!String.IsNullOrEmpty(docName)) {
PrintPreview.Document.DocumentName = docName;
}
labelsRequested = copies;
//PrintPreview.Document.PrinterSettings.Copies = (short)copies;
PrintPreview.SettingsFilename = Settings.PageSettingsLocation;
if (!PrintPreview.PrinterSelected) {
if (PrintPreview.ShowPrinterSelectDialog() != DialogResult.OK) {
return 0;
}
}
if (ShowPrintPreview) {
Size docSize = PrintPreview.Document.DefaultPageSettings.Bounds.Size;
float height = 0.8F * Screen.PrimaryScreen.WorkingArea.Size.Height;
float width = (height * docSize.Width) / docSize.Height;
Size winSize = new Size((int)width, (int)height);
PrintPreview.Height = winSize.Height;
PrintPreview.Width = winSize.Width;
PrintPreview.Document.PrinterSettings.Copies = (short)labelsRequested; // this may cause problems
PrintPreview.ShowDialog();
} else {
PrintPreview.PrintDocument();
}
return labelsPrinted;
}
现在,我没有像以前那样添加 print_Click
事件处理程序,而是连接了 Document
的 BeginPrint
和 >EndPrint
像这样:
Now, instead of adding the print_Click
event handler like I had before, I have wired up the Document
's BeginPrint
and EndPrint
like so:
void Document_BeginPrint(object sender, PrintEventArgs e) {
labelsPrinted = 0;
float fPerPage = LabelsHorizontal * LabelsVertical;
if (1 < fPerPage) {
float fQty = labelsRequested;
float fTotal = fQty / fPerPage;
PrintPreview.Document.PrinterSettings.Copies = (short)fTotal;
}
}
void Document_EndPrint(object sender, PrintEventArgs e) {
Printed = (labelsPrinted == labelsRequested);
}
不过,这里的关键显然来自我试图在 PrintPage
事件处理程序中设置 HasMorePages
值.
The key here, though, apparently came from me trying to set the HasMorePages
value in the PrintPage
event handler.
为什么?"你问.因为我只打印了多份相同的 1 页大小的文档.如果我的一个文档要跨越多个页面,那么我需要确保设置了HasMorePages
.
"Why?" you ask. Because I was only printing multiple copies of the same, 1-sheet sized document. If my one document were to span multiple pages, then I would need to ensure that HasMorePages
was set.
不用多说,这是我的 PrintPage
事件处理程序(请注意,此代码中的许多代码非常通用,可以轻松编辑以供其他人使用):
Without further ado, here is my PrintPage
event handler (note that a lot of this code is very universal and can be easily edited to work for others):
private void Document_Printed(object sender, PrintPageEventArgs e) {
float scale;
SizeF pageSize = new SizeF(
PrintPreview.Document.DefaultPageSettings.PaperSize.Width,
PrintPreview.Document.DefaultPageSettings.PaperSize.Height
);
Margins m = PrintPreview.Document.DefaultPageSettings.Margins;
float printableHeight = pageSize.Height - (m.Top + m.Bottom);
float printableWidth = pageSize.Width - (m.Left + m.Right);
if (printableWidth < printableHeight) {
if (labelSize.Width < labelSize.Height) {
float r1 = printableWidth / labelSize.Width;
float r2 = printableHeight / labelSize.Height;
scale = (r1 < r2) ? r1 : r2;
} else {
scale = printableWidth / labelSize.Width;
}
} else {
if (labelSize.Width < labelSize.Height) {
scale = (printableHeight) / labelSize.Height;
} else {
float r1 = printableWidth / labelSize.Width;
float r2 = printableHeight / labelSize.Height;
scale = (r1 < r2) ? r1 : r2;
}
}
float lh = scale * labelSize.Height;
float lw = scale * labelSize.Width;
float ml = scale * m.Left;
float mt = scale * m.Top;
Graphics G = e.Graphics;
G.SmoothingMode = smoothMode;
G.TextRenderingHint = TextRenderingHint.AntiAlias;
for (int i = 0; (i < LabelsHorizontal) && !e.Cancel; i++) {
float dx = i * (lw + ml); // Horizontal shift * scale
for (int j = 0; (j < LabelsVertical) && !e.Cancel; j++) {
float dy = j * (lh + mt); // Vertical shift * scale
#region ' Panels '
foreach (Panel item in panels) {
float h = scale * item.Size.Height;
float w = scale * item.Size.Width;
float x = (ml + dx) + scale * item.Location.X;
float y = (mt + dy) + scale * item.Location.Y;
using (SolidBrush b = new SolidBrush(item.BackColor)) {
G.FillRectangle(b, x, y, w, h);
}
using (Pen p = new Pen(Brushes.Black)) {
G.DrawRectangle(p, x, y, w, h);
}
}
#endregion
#region ' Logo '
if (logo != null) {
float h = scale * logo.Height;
float w = scale * logo.Width;
float x = (ml + dx) + scale * logoPt.X;
float y = (mt + dy) + scale * logoPt.Y;
G.DrawImage(logo, x, y, w, h);
}
#endregion
#region ' Labels '
foreach (Label item in labels) {
float h = scale * item.Size.Height;
float w = scale * item.Size.Width;
float x = (ml + dx) + scale * item.Location.X;
float y = (mt + dy) + scale * item.Location.Y;
Color c = PrintPreview.Document.DefaultPageSettings.Color ? item.ForeColor : Color.Black;
Font font = new Font(item.Font.FontFamily, scale * item.Font.Size, item.Font.Style);
using (SolidBrush b = new SolidBrush(c)) {
StringFormat format = GetStringFormatFromContentAllignment(item.TextAlign);
format.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
format.Trimming = StringTrimming.None;
PointF locationF = new PointF(x, y);
SizeF size = new SizeF(w, h);
RectangleF r = new RectangleF(locationF, size);
G.DrawString(item.Text, font, b, r, format);
}
}
#endregion
#region ' Barcodes '
foreach (AcpBarcodeControl item in barcodes) {
Image img = item.GetBarcodeImage(item.BarcodeText);
if (img != null) {
float h = scale * item.Size.Height;
float w = scale * item.Size.Width;
float x = (ml + dx) + scale * item.Location.X;
float y = (mt + dy) + scale * item.Location.Y;
G.DrawImage(img, x, y, w, h);
}
}
#endregion
labelsPrinted++;
}
}
}
这篇关于PrintPage PrintPageEventHandler 正在打印太多副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!