【问题标题】:PrintPage PrintPageEventHandler Is Printing Too Many CopiesPrintPage PrintPageEventHandler 打印的副本太多
【发布时间】:2012-04-23 20:12:18
【问题描述】:

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

为了帮助自己了解这些标签的效果,我使用 Windows 窗体来设计它们。这使我可以使用Label 控件定位我的文本、设置正确的字体等,添加自定义BarCode 控件,并使用Panel 控件获得“fancy”以对项目进行分组装进盒子里。

每个页面包含两 (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;
}

我必须编写一个自定义的 PrintPreview 类,该类将 PrintPreviewDialog 作为基类,以便我可以使用此 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 方法(代码的第一个sn-p)中,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,如果这有什么不同的话。

【问题讨论】:

  • @John Saunders:你为什么把C#从我的标题中去掉?
  • 因为您应该使用标签而不是标题来更好地识别(分类)您的问题。见when should we remove pseudo tags from a title
  • @Steve 是对的。我通常不会向有 1000 个或更多代表的用户讲授这个,但标签是放置标签的地方;不是标题。
  • 通过实现 PrintDocument.BeginPrint 事件的处理程序来重置页面计数器。使用调试器查看计数发生了什么。在 for 循环中设置退出条件看起来很可疑。我猜有些打印方式会超出页面末尾,并且打印机驱动程序会将其拆分为多个页面。
  • @nobugs:当我在我的 PC(使用 Adob​​e PDF 的 Windows 7)上进行测试时,打印的页数正确。 BeginPrint 有一个例程将计数设置为零,EndPrint 有一个例程设置AllPrinted = (labelQtyPrinted == PrintPreview.Document.PrinterSettings.Copies);

标签: c# winforms printing


【解决方案1】:

我明白了!

嬉皮士!

好的,如果有人在乎的话,这就是交易:我需要每页打印两 (2) 个标签。

我要做的是计算要打印多少页,使用垂直和水平打印的标签数量。

我添加了变量labelsRequested,并将现有变量labelQtyPrinted改名为labelsPrinted

private int labelsPrinted;
private int labelsRequested;

我的公共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 事件处理程序,而是像这样连接DocumentBeginPrintEndPrint

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++;
    }
  }
}

【讨论】:

  • 这怎么没有更多的赞成票?当我发现这个时,我正在寻求帮助来做同样的事情。谢谢!!!
  • 谢谢,@dev_JORD。我很高兴其他人可以使用它!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多