@@ -20,22 +20,23 @@ will popup.
2020
2121Additionally, we propose the ` SaveAsRequested ` event. You can register this
2222event to block the default dialog and use the ` SaveAsRequestedEventArgs `
23- instead, to set your preferred save as path, save as type, and duplicate file replacement rule. In your client app, you can design your own UI to input
24- these parameters. For HTML documents, we support 3 save as types: HTML_ONLY, SINGLE_FILE and COMPLETE. Non-HTML documents, must use DEFAULT, which will
23+ instead, to set your preferred save as path, save as type, and duplicate file
24+ replacement rule. In your client app, you can design your own UI to input
25+ these parameters. For HTML documents, we support 3 save as types: HTML_ONLY,
26+ SINGLE_FILE and COMPLETE. Non-HTML documents, must use DEFAULT, which will
2527save the content as it is. This API has default values for all parameters,
2628to perform the common save as operation.
2729
2830# Examples
29- ## Win32 C++
31+ ## Win32 C++
32+ ### Add or Remove the Event Handler
33+ This example hides the default save as dialog and shows a customized dialog.
3034``` c++
31- // ! [ToggleSilent]
32- // Turn on/off Silent SaveAs, which won't show the system default save as dialog.
33- // This example hides the default save as dialog and shows a customized dialog.
34- bool ScenarioSaveAs::ToggleSilent ()
35+ bool ScenarioSaveAs::ToggleEventHandler ()
3536{
3637 if (!m_webView2Staging20)
3738 return false;
38- if (m_silentSaveAs )
39+ if (m_hasSaveAsRequestedEventHandler )
3940 {
4041 // Unregister the handler for the `SaveAsRequested` event.
4142 m_webView2Staging20->remove_SaveAsRequested(m_saveAsRequestedToken);
@@ -50,14 +51,21 @@ bool ScenarioSaveAs::ToggleSilent()
5051 ICoreWebView2StagingSaveAsRequestedEventArgs* args) -> HRESULT
5152 {
5253 // Hide the system default save as dialog.
53- CHECK_FAILURE (args->put_Handled (TRUE));
54-
54+ CHECK_FAILURE (args->put_SuppressDefaultDialog (TRUE));
55+
5556 auto showCustomizedDialog = [ this, args]
5657 {
5758 // Preview the content mime type, optional
5859 wil::unique_cotaskmem_string mimeType;
5960 CHECK_FAILURE(args->get_ContentMimeType(&mimeType));
6061
62+
63+ // As an end developer, you can design your own dialog UI, or no UI at all.
64+ // You can ask the user information like file name, file extenstion, and etc.
65+ // Finally, concatenate and pass them into the event args
66+ //
67+ // This is a customized dialog example, the constructor returns after the
68+ // dialog interaction is completed by the end user.
6169 SaveAsDialog dialog(m_appWindow->GetMainWindow(), contentSaveTypes);
6270 if (dialog.confirmed)
6371 {
@@ -68,10 +76,15 @@ bool ScenarioSaveAs::ToggleSilent()
6876 args->put_ResultFilePath((LPCWSTR)dialog.path.c_str()));
6977 CHECK_FAILURE (args->put_SaveAsType(dialog.selectedType));
7078 CHECK_FAILURE(args->put_AllowReplace(dialog.allowReplace));
71-
72- // Confirm to download, required
73- CHECK_FAILURE (args->put_ConfirmToSave(TRUE));
7479 }
80+ else
81+ {
82+ // Save As cancelled from this customized dialog
83+ CHECK_FAILURE(args->put_Cancel(TRUE));
84+ }
85+
86+ // Indicate out parameters have been set.
87+ CHECK_FAILURE (args->put_Handled(TRUE));
7588 };
7689
7790 wil::com_ptr<ICoreWebView2Deferral> deferral;
@@ -88,17 +101,18 @@ bool ScenarioSaveAs::ToggleSilent()
88101 .Get(),
89102 &m_saveAsRequestedToken);
90103 }
91- m_silentSaveAs = !m_silentSaveAs ;
104+ m_hasSaveAsRequestedEventHandler = !m_hasSaveAsRequestedEventHandler ;
92105 MessageBox(
93106 m_appWindow->GetMainWindow(),
94- (m_silentSaveAs ? L"Silent Save As Enabled " : L"Silent Save As Disabled "), L"Info",
107+ (m_hasSaveAsRequestedEventHandler ? L"Event Handler Added " : L"Event Handler Rremoved "), L"Info",
95108 MB_OK);
96109 return true;
97110}
98- // ! [ToggleSilent]
111+ ```
112+ ### Programmatic Save As
113+ Call SaveContentAs method to trigger the programmatic save as.
114+ ``` c++
99115
100- // ! [ProgrammaticSaveAs]
101- // Call SaveContentAs method to trigger the programmatic save as.
102116bool ScenarioSaveAs::ProgrammaticSaveAs ()
103117{
104118 if (!m_webView2Staging20)
@@ -121,15 +135,15 @@ bool ScenarioSaveAs::ProgrammaticSaveAs()
121135 .Get());
122136 return true;
123137}
124- // ! [ProgrammaticSaveAs]
125138```
139+
126140# API Details
127141## Win32 C++
128142``` c++
129143// / Specifies save as type selection options for `ICoreWebView2Staging20`,
130144// / used in `SaveAsRequestedEventArgs`
131145// /
132- // / When the source is a html page, allows to select `HTML_ONLY`,
146+ // / When the source is a html page, supports to select `HTML_ONLY`,
133147// / `SINGLE_FILE`, `COMPLETE`; when the source is a non-html,
134148// / only allows to select `DEFAULT`; otherwise, will deny the download
135149// / and return `COREWEBVIEW2_SAVE_AS_TYPE_NOT_SUPPORTED`.
@@ -147,7 +161,7 @@ bool ScenarioSaveAs::ProgrammaticSaveAs()
147161 /// Save the page as mhtml
148162 COREWEBVIEW2_SAVE_AS_TYPE_SINGLE_FILE,
149163 /// Save the page as html, plus, download the page related source files in
150- /// a folder
164+ /// a same name directory
151165 COREWEBVIEW2_SAVE_AS_TYPE_COMPLETE,
152166} COREWEBVIEW2_SAVE_AS_TYPE;
153167
@@ -157,12 +171,24 @@ bool ScenarioSaveAs::ProgrammaticSaveAs()
157171 /// Programmatically open a system default save as dialog
158172 COREWEBVIEW2_SAVE_AS_OPEN_SYSTEM_DIALOG,
159173 /// Could not perform Save As because the destination file path is an invalid path.
174+ ///
175+ /// It is considered as invalid when:
176+ /// the path is empty, a relativate path, the parent directory doesn't
177+ /// exist, or the path is a driectory.
178+ ///
179+ /// Parent directory can be itself, if the path is root directory, or
180+ /// root disk. When the root doesn't exist, the path is invalid.
160181 COREWEBVIEW2_SAVE_AS_INVALID_PATH,
161182 /// Could not perform Save As because the destination file path already exists and
162183 /// replacing files was not allowed by the AllowReplace property.
163184 COREWEBVIEW2_SAVE_AS_FILE_ALREADY_EXISTS,
164185 /// Save as downloading not start as the ` SAVE_AS_TYPE ` selection not
165186 /// supported because of the content MIME type or system limits
187+ ///
188+ /// MIME type limits please see the emun ` COREWEBVIEW2_SAVE_AS_TYPE `
189+ ///
190+ /// System limits might happen when select ` HTML_ONLY ` for an error page,
191+ /// select ` COMPLETE ` and WebView running in an App Container, etc.
166192 COREWEBVIEW2_SAVE_AS_TYPE_NOT_SUPPORTED,
167193 /// Did not perform Save As because the client side decided to cancel.
168194 COREWEBVIEW2_SAVE_AS_CANCELLED,
@@ -188,14 +214,14 @@ interface ICoreWebView2Staging20 : IUnknown {
188214 /// Add an event handler for the ` SaveAsRequested ` event. This event is raised
189215 /// when save as is triggered, programmatically or manually.
190216 ///
191- /// \snippet ScenarioSaveAs.cpp ToggleSilent
217+ /// \snippet ScenarioSaveAs.cpp ToggleEventHandler
192218 HRESULT add_SaveAsRequested(
193219 [ in] ICoreWebView2StagingSaveAsRequestedEventHandler* eventHanlder,
194220 [ out] EventRegistrationToken* token);
195221
196222 /// Remove an event handler previously added with ` add_SaveAsRequested ` .
197223 ///
198- /// \snippet ScenarioSaveAs.cpp ToggleSilent
224+ /// \snippet ScenarioSaveAs.cpp ToggleEventHandler
199225 HRESULT remove_SaveAsRequested(
200226 [ in] EventRegistrationToken token);
201227}
@@ -215,26 +241,39 @@ interface ICoreWebView2StagingSaveAsRequestedEventArgs : IUnknown {
215241 /// Get the Mime type of content to be saved
216242 [ propget] HRESULT ContentMimeType([ out, retval] LPWSTR* value);
217243
218- /// Indicates if this event is a silent save as job. ` Handled ` as FALSE means
219- /// save as handled by system default dialog; TRUE means a silent save as,
220- /// will skip the system dialog .
244+ /// Indicates if pramameters in the event args has been set, TRUE means been set.
245+ ///
246+ /// The default value is FALSE .
221247 ///
222248 /// Set the ` Handled ` for save as
223- [ propput] HRESULT Handled ([ in] BOOL handled );
249+ [ propput] HRESULT Handled ([ in] BOOL value );
224250
225251 /// Get the ` Handled ` for save as
226- [ propget] HRESULT Handled ([ out, retval] BOOL* handled );
252+ [ propget] HRESULT Handled ([ out, retval] BOOL* value );
227253
228- /// Indicates if a silent save as confirm to download, TRUE means confirm.
229- /// when the event is invoked, the download will start. A programmatic call will
230- /// return COREWEBVIEW2_SAVE_AS_STARTED as well. set it FASLE to cancel save as
231- /// and will return COREWEBVIEW2_SAVE_AS_CANCELLED.
254+ /// Indicates if client side cancelled the silent save as, TRUE means cancelled.
255+ /// When the event is invoked, the download won't start. A programmatic call will
256+ /// return COREWEBVIEW2_SAVE_AS_CANCELLED as well.
232257 ///
233- /// Set the ` ConfrimToSave ` for save as
234- [ propput] HRESULT ConfirmToSave ([ in] BOOL confirmToSave);
258+ /// The default value is FALSE.
259+ ///
260+ /// Set the ` Cancel ` for save as
261+ [ propput] HRESULT Cancel ([ in] BOOL value);
235262
236- /// Get the ` ConfrimToSave ` for save as
237- [ propget] HRESULT ConfirmToSave ([ out, retval] BOOL* confirmToSave);
263+ /// Get the ` Cancel ` for save as
264+ [ propget] HRESULT Cancel ([ out, retval] BOOL* value);
265+
266+ /// Indicates if the system default dialog will be supressed, FALSE means
267+ /// save as default dialog will show; TRUE means a silent save as, will
268+ /// skip the system dialog.
269+ ///
270+ /// The default value is FALSE.
271+ ///
272+ /// Set the ` SupressDefaultDialog `
273+ [ propput] HRESULT SupressDefaultDialog([ in] BOOL value);
274+
275+ /// Get the ` SupressDefaultDialog `
276+ [ propget] HRESULT SupressDefaultDialog([ out, retval] BOOL* value);
238277
239278 /// Returns an ` ICoreWebView2Deferral ` object. This will defer showing the
240279 /// default Save As dialog and performing the Save As operation.
@@ -244,34 +283,45 @@ interface ICoreWebView2StagingSaveAsRequestedEventArgs : IUnknown {
244283 /// file name and extension. If ` ResultFilePath ` is not valid, e.g. root drive
245284 /// not exist, save as will be denied and return COREWEBVIEW2_SAVE_AS_INVALID_PATH.
246285 ///
286+ /// When the download complete and success, a target file will be saved at this
287+ /// location. If the SAVE_AS_TYPE is ` COMPLETE ` , will be an additional directory
288+ /// with resources files. The directory has the same name as filename, at the same
289+ /// location.
290+ ///
291+ /// The default value is a system suggested path, based on users' local environment.
292+ ///
247293 /// Set the ` ResultFilePath ` for save as
248- [ propput] HRESULT ResultFilePath ([ in] LPCWSTR resultFilePath );
294+ [ propput] HRESULT ResultFilePath ([ in] LPCWSTR value );
249295
250296 /// Get the ` ResultFilePath ` for save as
251- [ propget] HRESULT ResultFilePath ([ out, retval] LPWSTR* resultFilePath );
297+ [ propget] HRESULT ResultFilePath ([ out, retval] LPWSTR* value );
252298
253299 /// ` AllowReplace ` allows you to control what happens when a file already
254300 /// exists in the file path to which the Save As operation is saving.
255301 /// Setting this TRUE allows existing files to be replaced.
256302 /// Settings this FALSE will not replace existing files and will return
257303 /// COREWEBVIEW2_SAVE_AS_FILE_ALREADY_EXISTS.
258304 ///
305+ /// The default value is FALSE
306+ ///
259307 /// Set if allowed to replace the old file if duplicate happens in the save as job
260- [ propput] HRESULT AllowReplace ([ in] BOOL allowReplace );
308+ [ propput] HRESULT AllowReplace ([ in] BOOL value );
261309
262310 /// Get the duplicates replace rule for save as
263- [ propget] HRESULT AllowReplace ([ out, retval] BOOL* allowReplace );
311+ [ propget] HRESULT AllowReplace ([ out, retval] BOOL* value );
264312
265313 /// How to save documents with different types. See the enum
266314 /// COREWEBVIEW2_SAVE_AS_TYPE for a description of the different options.
267315 /// If the type isn't allowed for the current document,
268316 /// COREWEBVIEW2_SAVE_AS_TYPE_NOT_SUPPORT will be returned from SaveContentAs.
269317 ///
318+ /// The default value is COREWEBVIEW2_SAVE_AS_TYPE_DEFAULT
319+ ///
270320 /// Set the content save as type for save as job
271- [ propput] HRESULT SaveAsType ([ in] COREWEBVIEW2_SAVE_AS_TYPE type );
321+ [ propput] HRESULT SaveAsType ([ in] COREWEBVIEW2_SAVE_AS_TYPE value );
272322
273323 /// Get the content save as type for save as job
274- [ propget] HRESULT SaveAsType ([ out, retval] COREWEBVIEW2_SAVE_AS_TYPE* type );
324+ [ propget] HRESULT SaveAsType ([ out, retval] COREWEBVIEW2_SAVE_AS_TYPE* value );
275325}
276326
277327// / Receive the result for `SaveContentAs` method
0 commit comments