Skip to content

Commit a508f39

Browse files
authored
API Review: Default Download Dialog Positioning & Anchoring (#1810)
Add DefaultDownloadDialog.md Co-authored-by: Viktoria Zlatinova <vizlatin@microsoft.com>
1 parent 4bf587d commit a508f39

1 file changed

Lines changed: 258 additions & 0 deletions

File tree

specs/DefaultDownloadDialog.md

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
Default Download Dialog Positioning & Anchoring
2+
===
3+
4+
# Background
5+
This API gives you the ability to change the position of the default download dialog
6+
relative to the webview window, programmatically open and close the dialog, and
7+
make changes in response to the dialog opening or closing.
8+
9+
You can anchor the default download dialog to a button in your application by setting its
10+
position below your button, and alternating open and close calls when the button is
11+
clicked on.
12+
13+
For more complex customizations, you can use the Download APIs -
14+
[DownloadStarting](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2downloadstartingeventargs?view=webview2-1.0.961.33)
15+
and [DownloadOperation](https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2downloadoperation?view=webview2-1.0.961.33) - to build custom download UI.
16+
17+
# Examples
18+
```cpp
19+
void ViewComponent::CreateDownloadsButton()
20+
{
21+
CreateDownloadsToggleButton(m_downloadsButtonMargin, m_downloadsButtonWidth,
22+
m_downloadsButtonHeight);
23+
24+
// Subscribe to the `IsDefaultDownloadDialogOpenChanged` event
25+
// to make changes in response to the default download dialog
26+
// opening or closing. For example, if the dialog is anchored
27+
// to a button in the application, the button can change its appearance
28+
// depending on whether the dialog is opened or closed.
29+
CHECK_FAILURE(m_webView2_6->add_IsDefaultDownloadDialogOpenChanged(
30+
Callback<ICoreWebView2IsDefaultDownloadDialogOpenChangedEventHandler>(
31+
[this](ICoreWebView2* sender, IUnknown* args) -> HRESULT {
32+
BOOL isOpen;
33+
m_webView2_6->get_IsDefaultDownloadDialogOpen(&isOpen);
34+
// Update the "Show downloads" button state to match the dialog:
35+
// The button shows as pressed when the dialog is open.
36+
ShowDownloadsToggleButton().IsChecked(isOpen);
37+
return S_OK;
38+
})
39+
.Get(),
40+
&m_isDefaultDownloadDialogOpenChangedToken));
41+
}
42+
43+
void ViewComponent::ShowDownloadsToggleButton_OnToggle()
44+
{
45+
if (ShowDownloadsToggleButton().IsChecked().Value())
46+
{
47+
m_webview2_6->OpenDefaultDownloadDialog();
48+
}
49+
else
50+
{
51+
m_webview2_6->CloseDefaultDownloadDialog();
52+
}
53+
}
54+
55+
void ViewComponent::SetDefaultDownloadDialogPosition()
56+
{
57+
COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT cornerAlignment =
58+
COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT_TOP_LEFT;
59+
const int defaultMargin = 20;
60+
POINT margin = {defaultMargin, defaultMargin};
61+
CHECK_FAILURE(m_webView2_6->put_DefaultDownloadDialogCornerAlignment(
62+
cornerAlignment));
63+
CHECK_FAILURE(m_webView2_6->put_DefaultDownloadDialogMargin(margin));
64+
}
65+
```
66+
67+
```c#
68+
void CreateDownloadsButtonCmdExecuted(object target, ExecutedRoutedEventArgs e)
69+
{
70+
Button downloadsButton = new Button();
71+
downloadsButton.Content = "Downloads";
72+
downloadsButton.Click += new RoutedEventHandler(ToggleDownloadDialog);
73+
DockPanel.SetDock(downloadsButton, Dock.Left);
74+
dockPanel.Children.Insert(downloadsButton);
75+
76+
// Subscribe to the `IsDefaultDownloadDialogOpenChanged` event
77+
// to make changes in response to the default download dialog
78+
// opening or closing. For example, if the dialog is anchored to
79+
// a button in the application, the button appearance can change
80+
// depending on whether the dialog is opened or closed.
81+
webView.CoreWebView2.IsDefaultDownloadDialogOpenChanged +=
82+
(sender, args) =>
83+
{
84+
if (webView.CoreWebView2.IsDefaultDownloadDialogOpen)
85+
{
86+
downloadsButton.Background = new SolidColorBrush(Colors.LightBlue);
87+
}
88+
else
89+
{
90+
downloadsButton.Background = new SolidColorBrush(Colors.AliceBlue);
91+
}
92+
};
93+
}
94+
95+
void ToggleDownloadDialogCmdExecuted(object target, ExecutedRoutedEventArgs e)
96+
{
97+
if (webView.CoreWebView2.IsDefaultDownloadDialogOpen)
98+
{
99+
webView.CoreWebView2.CloseDefaultDownloadDialog();
100+
}
101+
else
102+
{
103+
webView.CoreWebView2.OpenDefaultDownloadDialog();
104+
}
105+
}
106+
107+
private void SetDefaultDownloadDialogPosition()
108+
{
109+
const int defaultMargin = 20;
110+
CoreWebView2DefaultDownloadDialogCornerAlignment cornerAlignment
111+
= CoreWebView2DefaultDownloadDialogCornerAlignment.TopLeft;
112+
System.Drawing.Point margin = new System.Drawing.Point(
113+
defaultMargin, defaultMargin);
114+
webView.CoreWebView2.DefaultDownloadDialogCornerAlignment =
115+
cornerAlignment;
116+
webView.CoreWebView2.DefaultDownloadDialogMargin = margin;
117+
}
118+
```
119+
120+
# API Details
121+
122+
123+
```c#
124+
[v1_enum]
125+
/// The default download dialog can be aligned to any of the WebView corners
126+
/// by setting the `DefaultDownloadDialogCornerAlignment` property. The default
127+
/// position is top-right corner.
128+
typedef enum COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT {
129+
130+
/// Top-left corner of the WebView.
131+
COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT_TOP_LEFT,
132+
133+
/// Top-right corner of the WebView.
134+
COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT_TOP_RIGHT,
135+
136+
/// Bottom-left corner of the WebView.
137+
COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT_BOTTOM_LEFT,
138+
139+
/// Bottom-right corner of the WebView.
140+
COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT_BOTTOM_RIGHT,
141+
142+
} COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT;
143+
144+
[uuid(9139c04d-8f37-42ae-8b63-01940c34d22f), object, pointer_default(unique)]
145+
interface ICoreWebView2_6 : ICoreWebView2_5
146+
{
147+
/// Raised when the `IsDefaultDownloadDialogOpen` property changes. This event
148+
/// comes after the `DownloadStarting` event. Setting the `Handled` property
149+
/// on the `DownloadStartingEventArgs` disables the default download dialog
150+
/// and ensures that this event is never raised.
151+
HRESULT add_IsDefaultDownloadDialogOpenChanged(
152+
[in] ICoreWebView2IsDefaultDownloadDialogOpenChangedEventHandler*
153+
handler,
154+
[out] EventRegistrationToken* token);
155+
156+
/// Remove an event handler previously added with
157+
/// `add_IsDefaultDownloadDialogOpenChanged`.
158+
HRESULT remove_IsDefaultDownloadDialogOpenChanged(
159+
[in] EventRegistrationToken token);
160+
161+
/// `TRUE` if the default download dialog is currently open. The value of this
162+
/// property changes only when the default download dialog is explicitly
163+
/// opened or closed. Hiding the WebView implicitly hides the dialog, but does
164+
/// not change the value of this property.
165+
[propget] HRESULT IsDefaultDownloadDialogOpen([out, retval] BOOL* value);
166+
167+
/// Open the default download dialog. If the dialog is opened before there
168+
/// are recent downloads, the dialog shows all past downloads for the
169+
/// current profile. Otherwise, the dialog shows only the recent downloads
170+
/// with a "See more" button for past downloads. Calling this method raises
171+
/// the `IsDefaultDownloadDialogOpenChanged` event if the dialog was closed.
172+
/// No effect if the dialog is already open.
173+
///
174+
/// \snippet ViewComponent.cpp ToggleDefaultDownloadDialog
175+
HRESULT OpenDefaultDownloadDialog();
176+
177+
/// Close the default download dialog. Calling this method raises the
178+
/// `IsDefaultDownloadDialogOpenChanged` event if the dialog was open. No
179+
/// effect if the dialog is already closed.
180+
HRESULT CloseDefaultDownloadDialog();
181+
182+
/// Get the default download dialog corner alignment.
183+
[propget] HRESULT DefaultDownloadDialogCornerAlignment(
184+
[out, retval] COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT* value);
185+
186+
/// Set the default download dialog corner alignment. The dialog can be
187+
/// aligned to any of the WebView corners (see
188+
/// COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT). When the WebView
189+
/// or dialog changes size, the dialog keeps its position relative to the
190+
/// corner. The dialog may become partially or completely outside of the
191+
/// WebView bounds if the WebView is small enough. Set the margin relative to
192+
/// the corner with the `DefaultDownloadDialogMargin` property.
193+
///
194+
/// \snippet ViewComponent.cpp SetDefaultDownloadDialogPosition
195+
[propput] HRESULT DefaultDownloadDialogCornerAlignment(
196+
[in] COREWEBVIEW2_DEFAULT_DOWNLOAD_DIALOG_CORNER_ALIGNMENT value);
197+
198+
/// Get the default download dialog margin.
199+
[propget] HRESULT DefaultDownloadDialogMargin([out, retval] POINT* value);
200+
201+
/// Set the default download dialog margin relative to the WebView corner
202+
/// specified by `DefaultDownloadDialogCornerAlignment`. The margin is a
203+
/// point that describes the vertical and horizontal distances between the
204+
/// chosen WebView corner and the default download dialog corner nearest to
205+
/// it. Positive values move the dialog towards the center of the WebView from
206+
/// the chosen WebView corner, and negative values move the dialog away from
207+
/// it. Use (0, 0) to align the dialog to the WebView corner with no margin.
208+
[propput] HRESULT DefaultDownloadDialogMargin([in] POINT value);
209+
}
210+
211+
/// Implements the interface to receive `IsDefaultDownloadDialogOpenChanged`
212+
/// events.
213+
[uuid(3117da26-ae13-438d-bd46-edbeb2c4ce81), object, pointer_default(unique)]
214+
interface ICoreWebView2IsDefaultDownloadDialogOpenChangedEventHandler : IUnknown {
215+
/// Provides the event args for the corresponding event. No event args exist
216+
/// and the `args` parameter is set to `null`.
217+
HRESULT Invoke([in] ICoreWebView2* sender, [in] IUnknown* args);
218+
}
219+
```
220+
221+
```c# (but really MIDL3)
222+
namespace Microsoft.Web.WebView2.Core
223+
{
224+
runtimeclass CoreWebView2;
225+
226+
enum CoreWebView2DefaultDownloadDialogCornerAlignment
227+
{
228+
TopLeft = 0,
229+
TopRight = 1,
230+
BottomLeft = 2,
231+
BottomRight = 3,
232+
};
233+
234+
runtimeclass CoreWebView2
235+
{
236+
[interface_name("Microsoft.Web.WebView2.Core.ICoreWebView2_6")]
237+
{
238+
// ICoreWebView2_6 members
239+
Boolean IsDefaultDownloadDialogOpen { get; };
240+
241+
event Windows.Foundation.TypedEventHandler<CoreWebView2, Object>
242+
IsDefaultDownloadDialogOpenChanged;
243+
244+
void OpenDefaultDownloadDialog();
245+
246+
void CloseDefaultDownloadDialog();
247+
248+
CoreWebView2DefaultDownloadDialogCornerAlignment
249+
DefaultDownloadDialogCornerAlignment { get; set; };
250+
251+
Windows.Foundation.Point DefaultDownloadDialogMargin { get; set; };
252+
}
253+
}
254+
}
255+
```
256+
257+
258+
# Appendix

0 commit comments

Comments
 (0)