Skip to content

Commit 81f86bb

Browse files
authored
API Review: PrintToPdf.md (#1522) (#1682)
* API Review: PrintToPdf.md (#1522) * print to pdf draft spec * update sample code to change setting * remove unused * internal review changes part 1 * api spec changes part 2 * update sample code * update documentation Co-authored-by: Viktoria Zlatinova <vizlatin@microsoft.com> * apply api review changes Co-authored-by: Viktoria Zlatinova <vizlatin@microsoft.com>
1 parent 112a738 commit 81f86bb

1 file changed

Lines changed: 330 additions & 0 deletions

File tree

specs/PrintToPdf.md

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
# Background
2+
3+
Developers have requested the ability to programmatically print to PDF in WebView2. Printing to PDF uses a virtual printer to create a PDF file from the current page. Currently the end user can do this from the print preview dialog by choosing the "Save as PDF" or "Microsoft Print to PDF" options. This API gives developers the ability to print to PDF without requiring the end user to go through the print preview dialog.
4+
5+
In this document we describe the updated API. We'd appreciate your feedback.
6+
7+
8+
# Description
9+
This API consists of an asynchronous PrintToPdf method and a PrintSettings object. The PrintToPdf method accepts a path that the PDF file should be saved to.
10+
11+
Use the CreatePrintSettings method to create a PrintSettings object with default values, which can be modified. The settings consist of: orientation, scale factor, page height and width, margins, printing of backgrounds, printing selection only, printing header and footer, header title, and footer URI. See API Details below for the default values.
12+
13+
Currently other programmatic printing is not supported.
14+
15+
# Examples
16+
```cpp
17+
// Shows the user a file selection dialog, then uses the selected path when
18+
// printing to PDF. If `enableLandscape` is true, the page is printed
19+
// in landscape mode, otherwise the page is printed in portrait mode.
20+
void FileComponent::PrintToPdf(bool enableLandscape)
21+
{
22+
WCHAR defaultName[MAX_PATH] = L"WebView2_PrintedPdf.pdf";
23+
OPENFILENAME openFileName = CreateOpenFileName(defaultName, L"PDF File\0*.pdf\0");
24+
if (GetSaveFileName(&openFileName))
25+
{
26+
wil::com_ptr<ICoreWebView2PrintSettings> printSettings = nullptr;
27+
if (enableLandscape)
28+
{
29+
wil::com_ptr<ICoreWebView2Environment5> webviewEnvironment5;
30+
CHECK_FAILURE(m_appWindow->GetWebViewEnvironment()->QueryInterface(
31+
IID_PPV_ARGS(&webviewEnvironment5)));
32+
if (webviewEnvironment5)
33+
{
34+
CHECK_FAILURE(webviewEnvironment5->CreatePrintSettings(&printSettings));
35+
CHECK_FAILURE(
36+
printSettings->put_Orientation(COREWEBVIEW2_PRINT_ORIENTATION_LANDSCAPE));
37+
}
38+
}
39+
40+
wil::com_ptr<ICoreWebView2_4> webview2_4;
41+
CHECK_FAILURE(m_webView->QueryInterface(IID_PPV_ARGS(&webview2_4)));
42+
if (webview2_4)
43+
{
44+
m_printToPdfInProgress = true;
45+
CHECK_FAILURE(webview2_4->PrintToPdf(
46+
openFileName.lpstrFile, printSettings.get(),
47+
Callback<ICoreWebView2PrintToPdfCompletedHandler>(
48+
[this](HRESULT errorCode, BOOL isSuccessful) -> HRESULT {
49+
CHECK_FAILURE(errorCode);
50+
m_printToPdfInProgress = false;
51+
auto showDialog = [isSuccessful] {
52+
MessageBox(
53+
nullptr,
54+
(isSuccessful) ? L"Print to PDF succeeded"
55+
: L"Print to PDF failed",
56+
L"Print to PDF Completed", MB_OK);
57+
};
58+
m_appWindow->RunAsync([showDialog]() { showDialog(); });
59+
return S_OK;
60+
})
61+
.Get()));
62+
}
63+
}
64+
}
65+
```
66+
67+
```c#
68+
// Prints current page to PDF using the default path and settings. If requested,
69+
// the orientation is changed to landscape.
70+
async void PrintToPdfCmdExecuted(object target, ExecutedRoutedEventArgs e)
71+
{
72+
if (_isPrintToPdfInProgress)
73+
{
74+
MessageBox.Show(this, "Print to PDF in progress", "Print To PDF");
75+
return;
76+
}
77+
CoreWebView2PrintSettings printSettings = null;
78+
string orientationString = e.Parameter.ToString();
79+
if (orientationString == "Landscape")
80+
{
81+
printSettings = WebViewEnvironment.CreatePrintSettings();
82+
printSettings.Orientation =
83+
CoreWebView2PrintOrientation.Landscape;
84+
}
85+
86+
Microsoft.Win32.SaveFileDialog saveFileDialog =
87+
new Microsoft.Win32.SaveFileDialog();
88+
saveFileDialog.InitialDirectory = "C:\\";
89+
saveFileDialog.Filter = "Pdf Files|*.pdf";
90+
Nullable<bool> result = saveFileDialog.ShowDialog();
91+
if (result == true) {
92+
_isPrintToPdfInProgress = true;
93+
bool isSuccessful = await webView.CoreWebView2.PrintToPdfAsync(
94+
saveFileDialog.FileName, printSettings);
95+
_isPrintToPdfInProgress = false;
96+
string message = (isSuccessful) ?
97+
"Print to PDF succeeded" : "Print to PDF failed";
98+
MessageBox.Show(this, message, "Print To PDF Completed");
99+
}
100+
}
101+
```
102+
# Remarks
103+
104+
# API Notes
105+
106+
107+
# API Details
108+
```
109+
interface ICoreWebView2_4;
110+
interface ICoreWebView2Environment5;
111+
interface ICoreWebView2PrintSettings;
112+
interface ICoreWebView2PrintToPdfCompletedHandler;
113+
114+
115+
/// The orientation for printing, used by the `Orientation` property on
116+
/// `ICoreWebView2SPrintSettings`. Currently only printing to PDF
117+
/// is supported.
118+
[v1_enum]
119+
typedef enum COREWEBVIEW2_PRINT_ORIENTATION
120+
{
121+
/// Print the page(s) in portrait orientation.
122+
COREWEBVIEW2_PRINT_ORIENTATION_PORTRAIT,
123+
124+
/// Print the page(s) in landscape orientation.
125+
COREWEBVIEW2_PRINT_ORIENTATION_LANDSCAPE,
126+
} COREWEBVIEW2_PRINT_ORIENTATION;
127+
128+
[uuid(9eae81c3-fe02-4084-b475-903a4ed9252e), object, pointer_default(unique)]
129+
interface ICoreWebView2_4 : IUnknown {
130+
/// Print the current page to PDF asynchronously with the provided settings. See
131+
/// `ICoreWebView2PrintSettings` for description of settings. Passing
132+
/// nullptr for `printSettings` results in default print settings used.
133+
///
134+
/// Use `resultFilePath` to specify the path to the PDF file. The host should
135+
/// provide an absolute path, including file name. If the path
136+
/// points to an existing file, the file will be overwritten. If the path is
137+
/// not valid, the method fails with `E_INVALIDARG`.
138+
///
139+
/// The async `PrintToPdf` operation completes when the data has been written
140+
/// to the PDF file. At this time the
141+
/// `ICoreWebView2PrintToPdfCompletedHandler` is invoked. If the
142+
/// application exits before printing is complete, the file is not saved.
143+
/// Only one `PrintToPdf` operation can be in progress at a time. If
144+
/// `PrintToPdf` is called while a print to PDF job is in progress, the
145+
/// completed handler is immediately invoked with `isSuccessful` set to FALSE.
146+
///
147+
/// \snippet FileComponent.cpp PrintToPdf
148+
HRESULT PrintToPdf(
149+
[in] LPCWSTR resultFilePath,
150+
[in] ICoreWebView2PrintSettings* printSettings,
151+
[in] ICoreWebView2PrintToPdfCompletedHandler* handler);
152+
}
153+
154+
/// Receives the result of the `PrintToPdf` method. If the print to PDF
155+
/// operation succeeds, `isSuccessful` is true. Otherwise, if the operation
156+
/// failed, `isSuccessful` is set to false. An invalid path returns
157+
/// `E_INVALIDARG`.
158+
[uuid(4808ac58-c372-4d3d-be5e-900df2593835), object, pointer_default(unique)]
159+
interface ICoreWebView2PrintToPdfCompletedHandler : IUnknown {
160+
161+
/// Provides the result of the corresponding asynchronous method.
162+
HRESULT Invoke([in] HRESULT errorCode, [in] LPCWSTR resultFilePath);
163+
}
164+
165+
/// Settings used by the `PrintToPdf` method. Other programmatic printing is not
166+
/// currently supported.
167+
[uuid(30964a64-2e92-4604-9eaa-3afcd3a015dc), object, pointer_default(unique)]
168+
interface ICoreWebView2PrintSettings : IUnknown {
169+
170+
/// The orientation can be portrait or landscape. The default orientation is
171+
/// portrait. See `COREWEBVIEW2_PRINT_ORIENTATION`.
172+
[propget] HRESULT Orientation(
173+
[out, retval] COREWEBVIEW2_PRINT_ORIENTATION* orientation);
174+
175+
/// Sets the `Orientation` property.
176+
[propput] HRESULT Orientation(
177+
[in] COREWEBVIEW2_PRINT_ORIENTATION orientation);
178+
179+
/// The scale factor is a value between 0.1 and 2.0. The default is 1.0.
180+
[propget] HRESULT ScaleFactor([out, retval] double* scaleFactor);
181+
182+
/// Sets the `ScaleFactor` property. Returns `E_INVALIDARG` if an invalid
183+
/// value is provided, and the current value is not changed.
184+
[propput] HRESULT ScaleFactor([in] double scaleFactor);
185+
186+
/// The page width in inches. The default width is 8.5 inches.
187+
[propget] HRESULT PageWidth([out, retval] double* pageWidth);
188+
189+
/// Sets the `PageWidth` property. Returns `E_INVALIDARG` if the page width is
190+
/// less than or equal to zero, and the current value is not changed.
191+
[propput] HRESULT PageWidth([in] double pageWidth);
192+
193+
/// The page height in inches. The default height is 11 inches.
194+
[propget] HRESULT PageHeight([out, retval] double* pageHeight);
195+
196+
/// Sets the `PageHeight` property. Returns `E_INVALIARG` if the page height
197+
/// is less than or equal to zero, and the current value is not changed.
198+
[propput] HRESULT PageHeight([in] double pageHeight);
199+
200+
/// The top margin in inches. The default is 1 cm, or ~0.4 inches.
201+
[propget] HRESULT MarginTop([out, retval] double* marginTop);
202+
203+
/// Sets the `MarginTop` property. A margin cannot be less than zero.
204+
/// Returns `E_INVALIDARG` if an invalid value is provided, and the current
205+
/// value is not changed.
206+
[propput] HRESULT MarginTop([in] double marginTop);
207+
208+
/// The bottom margin in inches. The default is 1 cm, or ~0.4 inches.
209+
[propget] HRESULT MarginBottom([out, retval] double* marginBottom);
210+
211+
/// Sets the `MarginBottom` property. A margin cannot be less than zero.
212+
/// Returns `E_INVALIDARG` if an invalid value is provided, and the current
213+
/// value is not changed.
214+
[propput] HRESULT MarginBottom([in] double marginBottom);
215+
216+
/// The left margin in inches. The default is 1 cm, or ~0.4 inches.
217+
[propget] HRESULT MarginLeft([out, retval] double* marginLeft);
218+
219+
/// Sets the `MarginLeft` property. A margin cannot be less than zero.
220+
/// Returns `E_INVALIDARG` if an invalid value is provided, and the current
221+
/// value is not changed.
222+
[propput] HRESULT MarginLeft([in] double marginLeft);
223+
224+
/// The right margin in inches. The default is 1 cm, or ~0.4 inches.
225+
[propget] HRESULT MarginRight([out, retval] double* marginRight);
226+
227+
/// Set the `MarginRight` property.A margin cannot be less than zero.
228+
/// Returns `E_INVALIDARG` if an invalid value is provided, and the current
229+
/// value is not changed.
230+
[propput] HRESULT MarginRight([in] double marginRight);
231+
232+
/// `TRUE` if background colors and images should be printed. The default value
233+
/// is `FALSE`.
234+
[propget] HRESULT ShouldPrintBackgrounds(
235+
[out, retval] BOOL* shouldPrintBackgrounds);
236+
237+
/// Set the `ShouldPrintBackgrounds` property.
238+
[propput] HRESULT ShouldPrintBackgrounds([in] BOOL shouldPrintBackgrounds);
239+
240+
/// `TRUE` if only the current end user's selection of HTML in the document
241+
/// should be printed. The default value is `FALSE`.
242+
[propget] HRESULT ShouldPrintSelectionOnly(
243+
[out, retval] BOOL* shouldPrintSelectionOnly);
244+
245+
/// Set the `ShouldPrintSelectionOnly` property.
246+
[propput] HRESULT ShouldPrintSelectionOnly(
247+
[in] BOOL shouldPrintSelectionOnly);
248+
249+
/// `TRUE` if header and footer should be printed. The default value is `FALSE`.
250+
/// The header consists of the date and time of printing, and the title of the
251+
/// page. The footer consists of the URI and page number. The height of the
252+
/// header and footer is 0.5 cm, or ~0.2 inches.
253+
[propget] HRESULT ShouldPrintHeaderAndFooter(
254+
[out, retval] BOOL* shouldPrintHeaderAndFooter);
255+
256+
/// Set the `ShouldPrintHeaderAndFooter` property.
257+
[propput] HRESULT ShouldPrintHeaderAndFooter(
258+
[in] BOOL shouldPrintHeaderAndFooter);
259+
260+
/// The title in the header if `ShouldPrintHeaderAndFooter` is `TRUE`. The
261+
/// default value is the title of the current document.
262+
[propget] HRESULT HeaderTitle([out, retval] LPWSTR* headerTitle);
263+
264+
/// Set the `HeaderTitle` property. If an empty string or null value is
265+
/// provided, no title is shown in the header.
266+
[propput] HRESULT HeaderTitle([in] LPCWSTR headerTitle);
267+
268+
/// The URI in the footer if `ShouldPrintHeaderAndFooter` is `TRUE`. The
269+
/// default value is the current URI.
270+
[propget] HRESULT FooterUri([out, retval] LPWSTR* footerUri);
271+
272+
/// Set the `FooterUri` property. If an empty string or null value is
273+
/// provided, no URI is shown in the footer.
274+
[propput] HRESULT FooterUri([in] LPCWSTR footerUri);
275+
}
276+
277+
[uuid(7dee69a9-c2cc-422b-9f86-e6ed6551ce95), object, pointer_default(unique)]
278+
interface ICoreWebView2Environment5 : IUnknown
279+
{
280+
/// Creates the `ICoreWebView2PrintSettings` used by the `PrintToPdf`
281+
/// method with default values.
282+
HRESULT CreatePrintSettings(
283+
[out, retval] ICoreWebView2PrintSettings** printSettings);
284+
}
285+
```
286+
287+
```c#
288+
namespace Microsoft.Web.WebView2.Core
289+
{
290+
runtimeclass CoreWebView2Environment;
291+
runtimeclass CoreWebView2PrintSettings;
292+
runtimeclass CoreWebView2;
293+
294+
enum CoreWebView2PrintOrientation
295+
{
296+
Portrait = 0,
297+
Landscape = 1,
298+
};
299+
300+
runtimeclass CoreWebView2PrintSettings
301+
{
302+
// ICoreWebView2PrintSettings members
303+
CoreWebView2PrintOrientation Orientation { get; set; };
304+
Double ScaleFactor { get; set; };
305+
Double PageWidth { get; set; };
306+
Double PageHeight { get; set; };
307+
Double MarginTop { get; set; };
308+
Double MarginBottom { get; set; };
309+
Double MarginLeft { get; set; };
310+
Double MarginRight { get; set; };
311+
Boolean ShouldPrintBackgrounds { get; set; };
312+
Boolean ShouldPrintSelectionOnly { get; set; };
313+
Boolean ShouldPrintHeaderAndFooter { get; set; };
314+
String HeaderTitle { get; set; };
315+
String FooterUri { get; set; };
316+
};
317+
318+
runtimeclass CoreWebView2Environment
319+
{
320+
CoreWebView2PrintSettings CreatePrintSettings();
321+
}
322+
323+
runtimeclass CoreWebView2
324+
{
325+
Windows.Foundation.IAsyncOperation<bool> PrintToPdfAsync(
326+
String ResultFilePath, CoreWebView2PrintSettings printSettings);
327+
}
328+
}
329+
```
330+
# Appendix

0 commit comments

Comments
 (0)