PrintPage PrintPageEventHandler 正在打印太多副本 [英] PrintPage PrintPageEventHandler Is Printing Too Many Copies

查看:23
本文介绍了PrintPage PrintPageEventHandler 正在打印太多副本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须为我们公司生产的产品打印运输标签.

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 事件处理程序,而是连接了 DocumentBeginPrint>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 正在打印太多副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆