【问题标题】:MSDN's multi-page printing example doesn't appear to work correctlyMSDN 的多页打印示例似乎无法正常工作
【发布时间】:2013-01-10 16:51:20
【问题描述】:

我正在关注 MSDN 关于打印多页的“操作方法”文档:How to: Print a Multi-Page Text File in Windows Forms

我已经将该页面上的示例变成了一个项目(尝试了 Visual Studio 2010 和 2012),发现它在打印少量页面时按预期工作,但在打印大量页面时(大约 9 页)它开始将开始页面呈现为空白(第一页和第二页是空白的,接下来的 15 页是正确的,等等)。

谁能确认这种行为?我看不出是什么原因造成的,也没有抛出异常。

这是我认为包含问题的代码部分:

private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
    int charactersOnPage = 0;
    int linesPerPage = 0;

    // Sets the value of charactersOnPage to the number of characters 
    // of stringToPrint that will fit within the bounds of the page.
    e.Graphics.MeasureString(stringToPrint, this.Font,
        e.MarginBounds.Size, StringFormat.GenericTypographic,
        out charactersOnPage, out linesPerPage);

    // Draws the string within the bounds of the page
    e.Graphics.DrawString(stringToPrint, this.Font, Brushes.Black,
        e.MarginBounds, StringFormat.GenericTypographic);

    // Remove the portion of the string that has been printed.
    stringToPrint = stringToPrint.Substring(charactersOnPage);

    // Check to see if more pages are to be printed.
    e.HasMorePages = (stringToPrint.Length > 0);
}

我认为没有任何数据类型被溢出。我用不同的打印机试过这个,但每一个都有相同的结果。

注意:我尝试过 .NET Framework 4 和 4.5,结果相同。

【问题讨论】:

  • 注意:我已经在多台计算机和操作系统上尝试过,结果相同。

标签: c# .net winforms visual-studio printing


【解决方案1】:

似乎 MSDN 示例无法正常工作。这可能是因为 MarginBounds Rectangle 是基于整数的,而不是基于浮点数的。将 Y 位置跟踪为浮点数并在 MeasureString 和 DrawString 方法中使用此值解决了问题。我通过检查different MSDN printing example 发现了这一点。

以下是相关代码:

private void pd_PrintPage(object sender, PrintPageEventArgs ev)
{
    float linesPerPage = 0;
    float yPos = 0;
    int count = 0;
    float leftMargin = ev.MarginBounds.Left;
    float topMargin = ev.MarginBounds.Top;
    string line = null;

    // Calculate the number of lines per page.
    linesPerPage = ev.MarginBounds.Height /
       printFont.GetHeight(ev.Graphics);

    // Print each line of the file.
    while (count < linesPerPage &&
       ((line = streamToPrint.ReadLine()) != null))
    {
        yPos = topMargin + (count *
           printFont.GetHeight(ev.Graphics));
        ev.Graphics.DrawString(line, printFont, Brushes.Black,
           leftMargin, yPos, new StringFormat());
        count++;
    }

    // If more lines exist, print another page.
    if (line != null)
        ev.HasMorePages = true;
    else
        ev.HasMorePages = false;
}

这并没有像上一个示例那样考虑自动换行,但可以相对轻松地实现。

【讨论】:

    【解决方案2】:

    这是旧的,但另一个似乎可行的解决方案是提取要打印的字符串。我认为 MSDN 示例可能会失败,因为初始字符串在打印完成之前被垃圾收集。

    private void printDocument1_PrintPage(object sender, PrintPageEventArgs e) {
    
         int charactersOnPage = 0;
         int linesPerPage = 0;
    
         // Sets the value of charactersOnPage to the number of characters
         // of stringToPrint that will fit within the bounds of the page.
         e.Graphics.MeasureString(stringToPrint, this.Font,
             e.MarginBounds.Size, StringFormat.GenericTypographic,
             out charactersOnPage, out linesPerPage);
     
         // Draws the string within the bounds of the page
         string tmp = stringToPrint.Substring(0, charactersOnPage);
         e.Graphics.DrawString(tmp, this.Font, Brushes.Black,
             e.MarginBounds, StringFormat.GenericTypographic);
     
         // Remove the portion of the string that has been printed.
         stringToPrint = stringToPrint.Substring(charactersOnPage);
     
         // Check to see if more pages are to be printed.
         e.HasMorePages = (stringToPrint.Length > 0); 
    }
    

    我认为这会保留引用直到操作完成。

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 2012-05-06
      • 2013-02-17
      • 2017-10-09
      • 2017-08-03
      • 2014-05-02
      • 2011-09-11
      • 2016-02-11
      • 1970-01-01
      相关资源
      最近更新 更多