我必须为我们公司生产的产品打印运输标签。
为了帮助自己了解这些标签的结果,我使用 Windows 窗体设计它们。这使我可以使用 Label
控件定位我的文本、正确设置字体等,添加自定义 BarCode
控件,并获得“fancy"使用 Panel
控件将项目分组到框中。
每个页面都有两 (2) 个标签。
当我的代码打印标签文档时,我请求 2、4 或 6 份副本。有时,也使用打印预览。在这种情况下,我必须重置创建的标签数。
但是,当文档打印时:
- 如果请求是 2 份,则代码打印 2 张纸(4 个标签)
- 如果请求是 4 份,则代码打印 8 张纸(16 个标签)
- 如果请求是 6 份,则代码会打印多达 18 页(36 个标签)
有没有人看到一个模式?我没有。
这是我的打印命令:
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;
}
我必须编写一个将 PrintPreviewDialog
作为基类的自定义 PrintPreview 类,以便我可以使用此 printButton_Click 方法覆盖其打印按钮:
// 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
事件的代码。
我的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”异常。
那么,为什么要制作这么多副本?
打印机是 HP LaserJet 4050,如果有任何区别的话。
最佳答案
我明白了!
耶皮!
好吧,如果有人关心的话,事情是这样的:我需要每页打印两 (2) 个标签。
我要做的是计算要打印的页数,使用要垂直和水平打印的标签数量。
我添加了变量 labelsRequested
并将现有变量 labelQtyPrinted
更改为 labelsPrinted
:
private int labelsPrinted;
private int labelsRequested;
我的公共(public) Print
方法更改为:
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
像这样:
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
值。
“为什么?”你问。因为我只是打印多份相同的 1 页大小的文档。 如果我的一个文档跨越多个页面,那么我需要确保 HasMorePages
已设置。
事不宜迟,这是我的 PrintPage
事件处理程序(请注意,很多代码都非常通用,可以轻松编辑以供其他人使用):
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++;
}
}
}
关于c# - PrintPage PrintPageEventHandler 正在打印太多副本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10287558/