Issue 932 attachment: PrintDocument.cs (5.7 KB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using System;
using System.Drawing.Printing;
using System.Windows.Forms;

namespace PdfGold.Renderer
{
/// <summary>
/// Implements printing of pages from a PDF document.
/// </summary>
public partial class PdfRenderer
{
// Invoking print dialog with UseEXDialog set from a toolstrip button
// has a known issue that the PrintDialog does not get the focus. This
// forces the user to click the Print or Cancel buttons twice. The
// following delegate is used to solve this problem by performing the
// operation asynchronously and allowing the .NET events to complete
// before the print dialog is displayed.
private delegate void PrintDocumentDelegate();

/// <summary>
/// Print the current document.
/// </summary>
public void PrintDocument()
{
BeginInvoke(new PrintDocumentDelegate(() =>
{
using (var form = new PrintDialog())
using (var pdf = new PdfPrintDocument(PdfDocument, PageNumber, Rotation))
{
form.AllowSomePages = PageCount > 1;
form.AllowCurrentPage = PageCount > 1;
form.Document = pdf;
form.UseEXDialog = true;

if (form.ShowDialog(this) == DialogResult.OK)
{
if (pdf.PrinterSettings.FromPage <= PageCount)
{
pdf.Print();
}
}
}
}));
}

private class PdfPrintDocument : PrintDocument
{
#region Instance Variables

public PdfDocument document;
private int pageNumber;
private readonly int currentPage;
private readonly PageRotation rotation;

#endregion

#region Properties

/// <summary>
/// If 'true', scale the image to fit the paper.
/// </summary>
public bool FitToPage { get; set; }

/// <summary>
/// If 'true', center the page on the paper.
/// </summary>
public bool CenterInPage { get; set; }

/// <summary>
/// If 'true', automatically determine portrait or landscape mode.
/// </summary>
public bool AutoOrient { get; set; }

#endregion

#region Constructor

public PdfPrintDocument(PdfDocument document, int currentPage, PageRotation rotation)
{
this.document = new PdfDocument(document);
this.currentPage = currentPage;
this.rotation = rotation;

PrinterSettings.FromPage = PrinterSettings.MinimumPage = 1;
PrinterSettings.ToPage = PrinterSettings.MaximumPage = document.PageCount;

FitToPage = true;
}

#endregion

#region Overrides

protected override void OnBeginPrint(PrintEventArgs e)
{
if (PrinterSettings.PrintRange == PrintRange.CurrentPage)
PrinterSettings.FromPage = PrinterSettings.ToPage = currentPage + 1;
pageNumber = PrinterSettings.FromPage - 1;
}

protected override void OnQueryPageSettings(QueryPageSettingsEventArgs e)
{
e.PageSettings.Landscape = PrinterSettings.DefaultPageSettings.Landscape || rotation == PageRotation.Degrees90 || rotation == PageRotation.Degrees270;
}

protected override void OnPrintPage(PrintPageEventArgs e)
{
if (pageNumber < document.PageCount)
{
var page = document.Pages[pageNumber];
if (document.Form != null)
{
page.Flatten(FlattenMode.Print);
page.Unload();
}

var rcPrint = new PdfRectangle(e.PageBounds.Left * e.Graphics.DpiX / 100, e.PageBounds.Top * e.Graphics.DpiX / 100, e.PageBounds.Right * e.Graphics.DpiX / 100, e.PageBounds.Bottom * e.Graphics.DpiX / 100);
var rcDisplay = new PdfRectangle(rcPrint);

if (FitToPage)
{
var rcPage = page.Bounds;
var zoom = Math.Min(rcPrint.Width / rcPage.Width, rcPrint.Height / rcPage.Height);
rcDisplay.Width = rcPage.Width * zoom;
rcDisplay.Height = rcPage.Height * zoom;
}

if (CenterInPage)
{
rcDisplay.Left += (rcPrint.Width - rcDisplay.Width) / 2;
rcDisplay.Top += (rcPrint.Height - rcDisplay.Height) / 2;
}

var options = RenderOptions.Annotations | RenderOptions.Printing;
if (!e.PageSettings.Color)
options |= RenderOptions.GrayScale;

page.Render(e.Graphics, rcDisplay.Rectangle, rotation, options);
}

e.HasMorePages = ++pageNumber < PrinterSettings.ToPage;
}

protected override void Dispose(bool disposing)
{
if (document != null)
{
document.Dispose();
document = null;
}
base.Dispose(disposing);
}
#endregion
}
}
}