Skip to content

Commit 6015054

Browse files
author
Eain Chen
committed
Add .net winrt code
1 parent 84bbe8e commit 6015054

File tree

1 file changed

+136
-18
lines changed

1 file changed

+136
-18
lines changed

specs/ProgrammaticSaveAs.md

Lines changed: 136 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,23 @@ This example hides the default save as dialog and shows a customized dialog.
3434
```c++
3535
bool ScenarioSaveAs::ToggleEventHandler()
3636
{
37-
if (!m_webView2Staging20)
37+
if (!m_webView2_20)
3838
return false;
39+
// m_hasSaveAsRequestedEventHandler indicates whether the event handler
40+
// has been subscribed.
3941
if (m_hasSaveAsRequestedEventHandler)
4042
{
4143
// Unregister the handler for the `SaveAsRequested` event.
42-
m_webView2Staging20->remove_SaveAsRequested(m_saveAsRequestedToken);
44+
m_webView2_20->remove_SaveAsRequested(m_saveAsRequestedToken);
4345
}
4446
else
4547
{
4648
// Register a handler for the `SaveAsRequested` event.
47-
m_webView2Staging20->add_SaveAsRequested(
48-
Callback<ICoreWebView2StagingSaveAsRequestedEventHandler>(
49+
m_webView2_20->add_SaveAsRequested(
50+
Callback<ICoreWebView2SaveAsRequestedEventHandler>(
4951
[this](
5052
ICoreWebView2* sender,
51-
ICoreWebView2StagingSaveAsRequestedEventArgs* args) -> HRESULT
53+
ICoreWebView2SaveAsRequestedEventArgs* args) -> HRESULT
5254
{
5355
// Hide the system default save as dialog.
5456
CHECK_FAILURE(args->put_SuppressDefaultDialog(TRUE));
@@ -59,7 +61,6 @@ bool ScenarioSaveAs::ToggleEventHandler()
5961
wil::unique_cotaskmem_string mimeType;
6062
CHECK_FAILURE(args->get_ContentMimeType(&mimeType));
6163

62-
6364
// As an end developer, you can design your own dialog UI, or no UI at all.
6465
// You can ask the user information like file name, file extenstion, and etc.
6566
// Finally, concatenate and pass them into the event args
@@ -112,10 +113,10 @@ Call RequestSaveAs method to trigger the programmatic save as.
112113

113114
bool ScenarioSaveAs::ProgrammaticSaveAs()
114115
{
115-
if (!m_webView2Staging20)
116+
if (!m_webView2_20)
116117
return false;
117-
m_webView2Staging20->RequestSaveAs(
118-
Callback<ICoreWebView2StagingRequestSaveAsCompletedHandler>(
118+
m_webView2_20->RequestSaveAs(
119+
Callback<ICoreWebView2RequestSaveAsCompletedHandler>(
119120
[this](HRESULT errorCode, COREWEBVIEW2_SAVE_AS_REQUESTED_RESULTS result) -> HRESULT
120121
{
121122
// Show RequestSaveAs returned result, optional
@@ -129,10 +130,77 @@ bool ScenarioSaveAs::ProgrammaticSaveAs()
129130
}
130131
```
131132

133+
## .Net/ WinRT
134+
### Add or Remove the Event Handler
135+
This example hides the default save as dialog and shows a customized dialog.
136+
```c#
137+
138+
void TaggleEventHandlerExecuted(object target, ExecutedRoutedEventArgs e)
139+
{
140+
if (hasSaveAsRequestedEventHandler)
141+
webView.CoreWebView2.SaveAsRequested -= WebView_SaveAsRequested;
142+
else
143+
webView.CoreWebView2.SaveAsRequested += WebView_SaveAsRequested;
144+
hasSaveAsRequestedEventHandler = !hasSaveAsRequestedEventHandler;
145+
MessageBox.Show(hasSaveAsRequestedEventHandler? "Event Handler Added":"Event Handler Rremoved" , "Info");
146+
}
147+
148+
void WebView_SaveAsRequested(object sender, CoreWebView2SaveAsRequestedEventArgs args)
149+
{
150+
// Hide the system default save as dialog.
151+
args.SuppressDefaultDialog = true;
152+
153+
// Developer can obtain a deferral for the event so that the CoreWebView2
154+
// doesn't examine the properties we set on the event args until
155+
// after the deferral completes asynchronously.
156+
CoreWebView2Deferral deferral = args.GetDeferral();
157+
158+
// We avoid potential reentrancy from running a message loop in the event
159+
// handler. Show the customized dialog later when complete the deferral
160+
// asynchronously.
161+
System.Threading.SynchronizationContext.Current.Post((_) =>
162+
{
163+
using (deferral)
164+
{
165+
// This is a customized dialog example, the constructor returns after the
166+
// dialog interaction is completed by the end user.
167+
var dialog = new SaveAsDialog(_Kinds);
168+
if (dialog.ShowDialog() == true)
169+
{
170+
// Preview the content mime type, optional.
171+
args.ContentMimeType;
172+
173+
// Setting parameters of event args from this dialog is optional.
174+
// The event args has default values.
175+
args.ResultFilePath = dialog.Directory.Text + "/" + dialog.Filename.Text;
176+
args.Kind = (CoreWebView2SaveAsRequestedKind)dialog.Kind.SelectedItem;
177+
args.AllowReplace = (bool)dialog.AllowReplaceOldFile.IsChecked;
178+
179+
}
180+
else
181+
{
182+
// Save As cancelled from this customized dialog
183+
args.Cancel = true;
184+
}
185+
}
186+
}, null);
187+
}
188+
```
189+
### Programmatic Save As
190+
Call RequestSaveAsAsync method to trigger the programmatic save as.
191+
```c#
192+
async void ProgrammaticSaveAsExecuted(object target, ExecutedRoutedEventArgs e)
193+
{
194+
CoreWebView2SaveAsRequestedResults result = await webView.CoreWebView2.RequestSaveAsAsync();
195+
// Show RequestSaveAsAsync returned result, optional
196+
MessageBox.Show(result.ToString(), "Info");
197+
}
198+
```
199+
132200
# API Details
133201
## Win32 C++
134202
```c++
135-
/// Specifies save as requested kind selection options for `ICoreWebView2Staging20`,
203+
/// Specifies save as requested kind selection options for `ICoreWebView2_20`,
136204
/// used in `SaveAsRequestedEventArgs`
137205
///
138206
/// When the source is a html page, supports to select `HTML_ONLY`,
@@ -183,12 +251,12 @@ bool ScenarioSaveAs::ProgrammaticSaveAs()
183251
/// Did not perform Save As because the client side decided to cancel.
184252
COREWEBVIEW2_SAVE_AS_REQUESTED_CANCELLED,
185253
/// Save as requested completeed, the downloading would start
186-
COREWEBVIEW2_SAVE_AS_REQUESTED_STARTED
254+
COREWEBVIEW2_SAVE_AS_REQUESTED_COMPLETED,
187255
} COREWEBVIEW2_SAVE_AS_REQUESTED_RESULTS;
188256

189257

190258
[uuid(15e1c6a3-c72a-4df3-91d7-d097fbec3bfd), object, pointer_default(unique)]
191-
interface ICoreWebView2Staging20 : IUnknown {
259+
interface ICoreWebView2_20 : IUnknown {
192260
/// Programmatically trigger a save as action for current content. `SaveAsRequested`
193261
/// event will be raised.
194262
///
@@ -200,14 +268,14 @@ interface ICoreWebView2Staging20 : IUnknown {
200268
/// Please see COREWEBVIEW2_SAVE_AS_REQUESTED_RESULTS
201269
///
202270
/// \snippet ScenarioSaveAs.cpp ProgrammaticSaveAs
203-
HRESULT SaveContentAs([in] ICoreWebView2StagingRequestSaveAsCompletedHandler* handler);
271+
HRESULT SaveContentAs([in] ICoreWebView2RequestSaveAsCompletedHandler* handler);
204272

205273
/// Add an event handler for the `SaveAsRequested` event. This event is raised
206274
/// when save as is triggered, programmatically or manually.
207275
///
208276
/// \snippet ScenarioSaveAs.cpp ToggleEventHandler
209277
HRESULT add_SaveAsRequested(
210-
[in] ICoreWebView2StagingSaveAsRequestedEventHandler* eventHanlder,
278+
[in] ICoreWebView2SaveAsRequestedEventHandler* eventHanlder,
211279
[out] EventRegistrationToken* token);
212280

213281
/// Remove an event handler previously added with `add_SaveAsRequested`.
@@ -219,15 +287,15 @@ interface ICoreWebView2Staging20 : IUnknown {
219287

220288
/// The event handler for the `SaveAsRequested` event.
221289
[uuid(55b86cd2-adfd-47f1-9cef-cdfb8c414ed3), object, pointer_default(unique)]
222-
interface ICoreWebView2StagingSaveAsRequestedEventHandler : IUnknown {
290+
interface ICoreWebView2SaveAsRequestedEventHandler : IUnknown {
223291
HRESULT Invoke(
224292
[in] ICoreWebView2* sender,
225-
[in] ICoreWebView2StagingSaveAsRequestedEventArgs* args);
293+
[in] ICoreWebView2SaveAsRequestedEventArgs* args);
226294
}
227295

228296
/// The event args for `SaveAsRequested` event
229297
[uuid(80101027-b8c3-49a1-a052-9ea4bd63ba47), object, pointer_default(unique)]
230-
interface ICoreWebView2StagingSaveAsRequestedEventArgs : IUnknown {
298+
interface ICoreWebView2SaveAsRequestedEventArgs : IUnknown {
231299
/// Get the Mime type of content to be saved
232300
[propget] HRESULT ContentMimeType([out, retval] LPWSTR* value);
233301

@@ -306,7 +374,57 @@ interface ICoreWebView2StagingSaveAsRequestedEventArgs : IUnknown {
306374

307375
/// Receive the result for `RequestSaveAs` method
308376
[uuid(1a02e9d9-14d3-41c6-9581-8d6e1e6f50fe), object, pointer_default(unique)]
309-
interface ICoreWebView2StagingRequestSaveAsCompletedHandler : IUnknown {
377+
interface ICoreWebView2RequestSaveAsCompletedHandler : IUnknown {
310378
HRESULT Invoke([in] HRESULT errorCode, [in] COREWEBVIEW2_REQUEST_SAVE_RESULTS result);
311379
}
312380
```
381+
382+
## .Net/ WinRT
383+
```c# (but really MIDL3)
384+
namespace Microsoft.Web.WebView2.Core
385+
{
386+
387+
runtimeclass CoreWebView2SaveAsRequestedEventArgs;
388+
runtimeclass CoreWebView2;
389+
390+
enum CoreWebView2SaveAsRequestedResults
391+
{
392+
InvalidPath = 0,
393+
FileAlreadyExists = 1,
394+
KindNotSupported = 2,
395+
Cancelled = 3,
396+
Completed = 4,
397+
};
398+
399+
enum CoreWebView2SaveAsRequestedKind
400+
{
401+
Default = 0,
402+
HtmlOnly = 1,
403+
SingleFile = 2,
404+
Complete = 3,
405+
};
406+
407+
runtimeclass CoreWebView2SaveAsRequestedEventArgs
408+
{
409+
String ContentMimeType { get; };
410+
Boolean Cancel { get; set; };
411+
Boolean SuppressDefaultDialog { get; set; };
412+
String ResultFilePath { get; set; };
413+
Boolean AllowReplace { get; set; };
414+
CoreWebView2SaveAsRequestedKind Kind { get; set; };
415+
Windows.Foundation.Deferral GetDeferral();
416+
};
417+
418+
runtimeclass CoreWebView2
419+
{
420+
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2_20")]
421+
{
422+
// ...
423+
event Windows.Foundation.TypedEventHandler
424+
<CoreWebView2, CoreWebView2SaveAsRequestedEventArgs> SaveAsRequested;
425+
Windows.Foundation.IAsyncOperation<CoreWebView2SaveAsRequestedResults >
426+
RequestSaveAsAsync();
427+
}
428+
};
429+
}
430+
```

0 commit comments

Comments
 (0)