Skip to content

Commit bf2c558

Browse files
author
Eain Chen
committed
Update with spec review comments
- More accurate the description for different Kind, including top-level document, subresources, wiki link. - Rewrite the sample code. The methods of add event handler were removed. In new sample code, one method will both register handler and call save as. - Add comment to address get_ContentMimeType can help the Kind selection. - Add comment to address the CoreWebView2SaveAsUIResults will help end developer know the error if API call failed.
1 parent cecc290 commit bf2c558

File tree

1 file changed

+61
-77
lines changed

1 file changed

+61
-77
lines changed

specs/ProgrammaticSaveAs.md

Lines changed: 61 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -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

1110
With 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

1716
The 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,
2019
which will go through the existing WebView2 download APIs.
2120

2221
We'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
4241
This 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
133121
This 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)]
246230
interface 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

Comments
 (0)