@@ -3,10 +3,9 @@ Programmatic Save As API
33
44# Background
55
6- Chromium browser's context menus have a "Save as" menu item to save the top level
7- document (html page, image, pdf, or other content) through a save as dialog. We
8- provide more flexible ways to programmatically perform the Save As operation in
9- WebView2.
6+ Chromium browser's context menus have a "Save as" menu item to save the document
7+ (html page, image, pdf, or other content) through a save as dialog. We provide
8+ more flexible ways to programmatically perform the Save As operation in WebView2.
109
1110With the new API you will be able to:
1211- Launch the default save as dialog
@@ -15,8 +14,8 @@ With the new API you will be able to:
1514- Build your own save as UI
1615
1716The chromium browser's Save As operation consists of showing the Save As dialog
18- and then starting a download of the top level document. The Save As method and
19- event described in this document relate to the Save As dialog and not the download,
17+ and then starting a download of the document. The Save As method and event
18+ described in this document relate to the Save As dialog and not the download,
2019which will go through the existing WebView2 download APIs.
2120
2221We'd appreciate your feedback.
@@ -38,10 +37,11 @@ save as operation.
3837
3938# Examples
4039## Win32 C++
41- ### Add the Event Handler
40+ ### Programmatic Save As
4241This example hides the default save as dialog and shows a customized dialog.
42+ The sample code will register a handler and trigger programmaic save as once.
4343``` c++
44- bool ScenarioSaveAs::AddEventHandler ()
44+ bool ScenarioSaveAs::ProgrammaticSaveAs ()
4545{
4646 if (!m_webView2_20)
4747 return false;
@@ -72,8 +72,7 @@ bool ScenarioSaveAs::AddEventHandler()
7272 // args has default values based on the document to save.
7373 //
7474 // Additionally, you can use ` get_ContentMimeType ` to check the mime
75- // type of the document that will be saved to help setup your custom
76- // Save As dialog UI
75+ // type of the document that will be saved to help the Kind selection.
7776 CHECK_FAILURE(
7877 args->put_SaveAsFilePath((LPCWSTR)dialog.path.c_str()));
7978 CHECK_FAILURE(args->put_Kind(dialog.selectedKind));
@@ -99,25 +98,14 @@ bool ScenarioSaveAs::AddEventHandler()
9998 })
10099 .Get(),
101100 &m_SaveAsUIShowingToken);
102-
103- MessageBox(
104- m_appWindow->GetMainWindow(), L"Event Handler Added", L"Info",MB_OK);
105- return true;
106- }
107- ```
108- ### Programmatic Save As
109- Call ShowSaveAsUI method to trigger the programmatic save as.
110- ``` c++
111-
112- bool ScenarioSaveAs::ProgrammaticSaveAs ()
113- {
114- if (!m_webView2_20)
115- return false;
101+
102+ // Call method ShowSaveAsUI to trigger the programmatic save as once.
116103 m_webView2_20->ShowSaveAsUI(
117104 Callback<ICoreWebView2ShowSaveAsUICompletedHandler >(
118105 [ this] (HRESULT errorCode, COREWEBVIEW2_SAVE_AS_UI_RESULT result) -> HRESULT
119106 {
120- // Show ShowSaveAsUI returned result, optional
107+ // Show ShowSaveAsUI returned result, optional. See
108+ // COREWEBVIEW2_SAVE_AS_UI_RESULT for more details.
121109 MessageBox(
122110 m_appWindow->GetMainWindow(),
123111 (L"Save As " + saveAsUIString[ result] ).c_str(), L"Info", MB_OK);
@@ -129,64 +117,58 @@ bool ScenarioSaveAs::ProgrammaticSaveAs()
129117```
130118
131119## .Net/ WinRT
132- ### Add the Event Handler
120+ ### Programmatic Save As
133121This example hides the default save as dialog and shows a customized dialog.
122+ The sample code will register a handler and trigger programmaic save as once.
134123``` c#
135124
136- void AddEventHandlerExecuted (object target , ExecutedRoutedEventArgs e )
125+ async void ProgrammaticSaveAsExecuted (object target , ExecutedRoutedEventArgs e )
137126{
138- webView .CoreWebView2 .SaveAsUIShowing += WebView_SaveAsUIShowing ;
139- MessageBox .Show (" Event Handler Added" , " Info" );
140- }
141-
142- void WebView_SaveAsUIShowing (object sender , CoreWebView2SaveAsUIShowingEventArgs args )
143- {
144- // Hide the system default save as dialog.
145- args .SuppressDefaultDialog = true ;
146-
147- // Developer can obtain a deferral for the event so that the CoreWebView2
148- // doesn't examine the properties we set on the event args until
149- // after the deferral completes asynchronously.
150- CoreWebView2Deferral deferral = args .GetDeferral ();
151-
152- // We avoid potential reentrancy from running a message loop in the event
153- // handler. Show the customized dialog later then complete the deferral
154- // asynchronously.
155- System .Threading .SynchronizationContext .Current .Post ((_ ) =>
127+ // Register a handler for the `SaveAsUIShowing` event.
128+ webView .CoreWebView2 .SaveAsUIShowing += (sender , args ) =>
156129 {
157- using (deferral )
130+ // Hide the system default save as dialog.
131+ args .SuppressDefaultDialog = true ;
132+
133+ // Developer can obtain a deferral for the event so that the CoreWebView2
134+ // doesn't examine the properties we set on the event args until
135+ // after the deferral completes asynchronously.
136+ CoreWebView2Deferral deferral = args .GetDeferral ();
137+
138+ // We avoid potential reentrancy from running a message loop in the event
139+ // handler. Show the customized dialog later then complete the deferral
140+ // asynchronously.
141+ System .Threading .SynchronizationContext .Current .Post ((_ ) =>
158142 {
159- // This is a customized dialog example.
160- var dialog = new SaveAsDialog ();
161- if (dialog .ShowDialog () == true )
162- {
163- // Setting parameters of event args from this dialog is optional.
164- // The event args has default values.
165- //
166- // Additionally, you can use `args.ContentMimeType` to check the mime
167- // type of the document that will be saved to help setup your custom
168- // Save As dialog UI
169- args .SaveAsFilePath = System .IO .Path .Combine (
170- dialog .Directory .Text , dialog .Filename .Text );
171- args .Kind = (CoreWebView2SaveAsKind )dialog .Kind .SelectedItem ;
172- args .AllowReplace = (bool )dialog .AllowReplaceOldFile .IsChecked ;
173- }
174- else
143+ using (deferral )
175144 {
176- // Save As cancelled from this customized dialog
177- args .Cancel = true ;
145+ // This is a customized dialog example.
146+ var dialog = new SaveAsDialog ();
147+ if (dialog .ShowDialog () == true )
148+ {
149+ // Setting parameters of event args from this dialog is optional.
150+ // The event args has default values.
151+ //
152+ // Additionally, you can use `args.ContentMimeType` to check the mime
153+ // type of the document that will be saved to help the Kind selection.
154+ args .SaveAsFilePath = System .IO .Path .Combine (
155+ dialog .Directory .Text , dialog .Filename .Text );
156+ args .Kind = (CoreWebView2SaveAsKind )dialog .Kind .SelectedItem ;
157+ args .AllowReplace = (bool )dialog .AllowReplaceOldFile .IsChecked ;
158+ }
159+ else
160+ {
161+ // Save As cancelled from this customized dialog
162+ args .Cancel = true ;
163+ }
178164 }
179- }
180- }, null );
181- }
182- ```
183- ### Programmatic Save As
184- Call ShowSaveAsUIAsync method to trigger the programmatic save as.
185- ``` c#
186- async void ProgrammaticSaveAsExecuted (object target , ExecutedRoutedEventArgs e )
187- {
165+ }, null );
166+ };
167+
168+ // Call ShowSaveAsUIAsync method to trigger the programmatic save as once.
188169 CoreWebView2SaveAsUIResults result = await webView .CoreWebView2 .ShowSaveAsUIAsync ();
189- // Show ShowSaveAsUIAsync returned result, optional
170+ // Show ShowSaveAsUIAsync returned result, optional. See
171+ // CoreWebView2SaveAsUIResults for more details.
190172 MessageBox .Show (result .ToString (), " Info" );
191173}
192174```
@@ -204,9 +186,11 @@ async void ProgrammaticSaveAsExecuted(object target, ExecutedRoutedEventArgs e)
204186 /// Default to save for a non-html content. If it is selected for a html
205187 /// page, it’s same as HTML_ONLY option.
206188 COREWEBVIEW2_SAVE_AS_KIND_DEFAULT,
207- /// Save the page as html
189+ /// Save the page as html. It only saves top-level document, excludes
190+ /// subresource.
208191 COREWEBVIEW2_SAVE_AS_KIND_HTML_ONLY,
209- /// Save the page as mhtml
192+ /// Save the page as mhtml.
193+ /// Read more about mhtml at (https://en.wikipedia.org/wiki/MHTML )
210194 COREWEBVIEW2_SAVE_AS_KIND_SINGLE_FILE,
211195 /// Save the page as html, plus, download the page related source files
212196 /// (for example CSS, JavaScript, images, and so on) in a directory with
@@ -244,7 +228,7 @@ async void ProgrammaticSaveAsExecuted(object target, ExecutedRoutedEventArgs e)
244228
245229[uuid(15e1c6a3-c72a-4df3-91d7-d097fbec3bfd), object, pointer_default(unique)]
246230interface ICoreWebView2_20 : IUnknown {
247- /// Programmatically trigger a save as action for the current top-level document.
231+ /// Programmatically trigger a save as action for the currently loaded document.
248232 /// The ` SaveAsUIShowing ` event will be raised.
249233 ///
250234 /// Opens a system modal dialog by default. If the ` SuppressDefaultDialog ` is TRUE,
0 commit comments