Skip to content

Commit bce5a77

Browse files
Merge pull request #242 from MicrosoftEdge/smoketest/1.0.2526-testing
Update projects to use latest WebView2 1.0.2526 prerelease
2 parents 928fe12 + 2b0d774 commit bce5a77

17 files changed

+647
-222
lines changed

SampleApps/WebView2APISample/AppWindow.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@
3838
#include "ScenarioDOMContentLoaded.h"
3939
#include "ScenarioDragDrop.h"
4040
#include "ScenarioExtensionsManagement.h"
41+
#include "ScenarioFileSystemHandleShare.h"
4142
#include "ScenarioIFrameDevicePermission.h"
4243
#include "ScenarioNavigateWithWebResourceRequest.h"
4344
#include "ScenarioNonClientRegionSupport.h"
4445
#include "ScenarioNotificationReceived.h"
4546
#include "ScenarioPermissionManagement.h"
46-
#include "ScenarioFileSystemHandleShare.h"
47+
#include "ScenarioSaveAs.h"
4748
#include "ScenarioSharedBuffer.h"
4849
#include "ScenarioSharedWorkerWRR.h"
4950
#include "ScenarioVirtualHostMappingForPopUpWindow.h"
@@ -1334,11 +1335,11 @@ void AppWindow::InitializeWebView()
13341335
CHECK_FAILURE(options6->put_AreBrowserExtensionsEnabled(TRUE));
13351336
}
13361337

1337-
Microsoft::WRL::ComPtr<ICoreWebView2ExperimentalEnvironmentOptions2> exp_options2;
1338-
if (options.As(&exp_options2) == S_OK)
1338+
Microsoft::WRL::ComPtr<ICoreWebView2EnvironmentOptions8> options8;
1339+
if (options.As(&options8) == S_OK)
13391340
{
13401341
COREWEBVIEW2_SCROLLBAR_STYLE style = COREWEBVIEW2_SCROLLBAR_STYLE_FLUENT_OVERLAY;
1341-
CHECK_FAILURE(exp_options2->put_ScrollBarStyle(style));
1342+
CHECK_FAILURE(options8->put_ScrollBarStyle(style));
13421343
}
13431344

13441345
HRESULT hr = CreateCoreWebView2EnvironmentWithOptions(
@@ -1609,6 +1610,8 @@ HRESULT AppWindow::OnCreateCoreWebView2ControllerCompleted(
16091610
}
16101611
NewComponent<ScenarioPermissionManagement>(this);
16111612
NewComponent<ScenarioNotificationReceived>(this);
1613+
NewComponent<ScenarioSaveAs>(this);
1614+
16121615
// We have a few of our own event handlers to register here as well
16131616
RegisterEventHandlers();
16141617

SampleApps/WebView2APISample/ScenarioFileSystemHandleShare.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,4 @@ ScenarioFileSystemHandleShare::ScenarioFileSystemHandleShare(AppWindow* appWindo
7171
ScenarioFileSystemHandleShare::~ScenarioFileSystemHandleShare()
7272
{
7373
CHECK_FAILURE(m_webView->remove_WebMessageReceived(m_navigationCompletedToken));
74-
}
74+
}
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
// Copyright (C) Microsoft Corporation. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "stdafx.h"
6+
7+
#include "ScenarioSaveAs.h"
8+
9+
#include "App.h"
10+
#include "AppWindow.h"
11+
#include "CheckFailure.h"
12+
#include "Shlwapi.h"
13+
#include "TextInputDialog.h"
14+
#include "resource.h"
15+
16+
using namespace Microsoft::WRL;
17+
18+
ScenarioSaveAs::ScenarioSaveAs(AppWindow* appWindow)
19+
: m_appWindow(appWindow), m_webView(appWindow->GetWebView())
20+
{
21+
if (m_webView)
22+
{
23+
m_webView2Experimental25 = m_webView.try_query<ICoreWebView2Experimental25>();
24+
}
25+
}
26+
27+
std::initializer_list<COREWEBVIEW2_SAVE_AS_KIND> saveAsKind{
28+
COREWEBVIEW2_SAVE_AS_KIND_DEFAULT, COREWEBVIEW2_SAVE_AS_KIND_HTML_ONLY,
29+
COREWEBVIEW2_SAVE_AS_KIND_SINGLE_FILE, COREWEBVIEW2_SAVE_AS_KIND_COMPLETE};
30+
// Sync with COREWEBVIEW2_SAVE_AS_KIND.
31+
std::array<std::wstring, 4> saveAsKindString{
32+
L"DEFAULT", L"HTML_ONLY", L"SIGNLE_FILE", L"COMPLETE"};
33+
// Sync with COREWEBVIEW2_SAVE_AS_UI_RESULTS.
34+
std::array<std::wstring, 5> saveAsUIResultString{
35+
L"SUCCESS", L"INVALID_PATH", L"FILE_ALREADY_EXISTS", L"KIND_NOT_SUPPORTED", L"CANCELLED"};
36+
37+
//! [ToggleSilent]
38+
// Turn on/off Silent SaveAs, which won't show the system default save as dialog.
39+
// This example hides the default save as dialog and shows a customized dialog.
40+
bool ScenarioSaveAs::ToggleSilent()
41+
{
42+
if (!m_webView2Experimental25)
43+
return false;
44+
m_silentSaveAs = !m_silentSaveAs;
45+
if (m_silentSaveAs && m_saveAsUIShowingToken.value == 0)
46+
{
47+
// Register a handler for the `SaveAsUIShowing` event.
48+
m_webView2Experimental25->add_SaveAsUIShowing(
49+
Callback<ICoreWebView2ExperimentalSaveAsUIShowingEventHandler>(
50+
[this](
51+
ICoreWebView2* sender,
52+
ICoreWebView2ExperimentalSaveAsUIShowingEventArgs* args) -> HRESULT
53+
{
54+
// Hide the system default save as dialog.
55+
CHECK_FAILURE(args->put_SuppressDefaultDialog(TRUE));
56+
57+
auto showCustomizedDialog = [this, args = wil::make_com_ptr(args)]
58+
{
59+
// Preview the content mime type, optional.
60+
wil::unique_cotaskmem_string mimeType;
61+
CHECK_FAILURE(args->get_ContentMimeType(&mimeType));
62+
63+
SaveAsDialog dialog(m_appWindow->GetMainWindow(), saveAsKind);
64+
if (dialog.confirmed)
65+
{
66+
// Set the SaveAsFilePath, Kind, AllowReplace for the event
67+
// args from this customized dialog inputs, optional. If nothing
68+
// needs to input, the event args will provide default values.
69+
CHECK_FAILURE(args->put_SaveAsFilePath(dialog.path.c_str()));
70+
CHECK_FAILURE(args->put_Kind(dialog.selectedKind));
71+
CHECK_FAILURE(args->put_AllowReplace(dialog.allowReplace));
72+
73+
BOOL allowReplace;
74+
CHECK_FAILURE(args->get_AllowReplace(&allowReplace));
75+
wil::unique_cotaskmem_string path;
76+
CHECK_FAILURE(args->get_SaveAsFilePath(&path));
77+
COREWEBVIEW2_SAVE_AS_KIND selectedKind;
78+
CHECK_FAILURE(args->get_Kind(&selectedKind));
79+
80+
// Preview silent save as event args inputs, optional.
81+
MessageBox(
82+
m_appWindow->GetMainWindow(),
83+
(std::wstring(L"Content Mime Type: ") + mimeType.get() + L"\n" +
84+
L"Fullpath: " + path.get() + L"\n" + L"Allow Replace: " +
85+
(allowReplace ? L"true" : L"false") + L"\n" +
86+
L"Selected Save As Kind: " + saveAsKindString[selectedKind])
87+
.c_str(),
88+
L"Silent Save As Parameters Preview", MB_OK);
89+
}
90+
else
91+
{
92+
// Save As cancelled from this customized dialog.
93+
CHECK_FAILURE(args->put_Cancel(TRUE));
94+
}
95+
};
96+
97+
wil::com_ptr<ICoreWebView2Deferral> deferral;
98+
CHECK_FAILURE(args->GetDeferral(&deferral));
99+
100+
m_appWindow->RunAsync(
101+
[deferral, showCustomizedDialog]()
102+
{
103+
showCustomizedDialog();
104+
CHECK_FAILURE(deferral->Complete());
105+
});
106+
return S_OK;
107+
})
108+
.Get(),
109+
&m_saveAsUIShowingToken);
110+
}
111+
else
112+
{
113+
// Unregister the handler for the `SaveAsUIShowing` event.
114+
m_webView2Experimental25->remove_SaveAsUIShowing(m_saveAsUIShowingToken);
115+
m_saveAsUIShowingToken.value = 0;
116+
}
117+
MessageBox(
118+
m_appWindow->GetMainWindow(),
119+
(m_silentSaveAs ? L"Silent Save As Enabled" : L"Silent Save As Disabled"), L"Info",
120+
MB_OK);
121+
return true;
122+
}
123+
//! [ToggleSilent]
124+
125+
//! [ProgrammaticSaveAs]
126+
// Call ShowSaveAsUI method to trigger the programmatic save as.
127+
bool ScenarioSaveAs::ProgrammaticSaveAs()
128+
{
129+
if (!m_webView2Experimental25)
130+
return false;
131+
m_webView2Experimental25->ShowSaveAsUI(
132+
Callback<ICoreWebView2ExperimentalShowSaveAsUICompletedHandler>(
133+
[this](HRESULT errorCode, COREWEBVIEW2_SAVE_AS_UI_RESULT result) -> HRESULT
134+
{
135+
// Show ShowSaveAsUI returned result, optional.
136+
MessageBox(
137+
m_appWindow->GetMainWindow(),
138+
(L"ShowSaveAsUI " + saveAsUIResultString[result]).c_str(), L"Info", MB_OK);
139+
return S_OK;
140+
})
141+
.Get());
142+
return true;
143+
}
144+
//! [ProgrammaticSaveAs]
145+
146+
bool ScenarioSaveAs::HandleWindowMessage(
147+
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* result)
148+
{
149+
if (message == WM_COMMAND)
150+
{
151+
switch (LOWORD(wParam))
152+
{
153+
case IDM_SCENARIO_SAVE_AS_TOGGLE_SILENT:
154+
{
155+
return ToggleSilent();
156+
}
157+
case IDM_SCENARIO_SAVE_AS_PROGRAMMATIC:
158+
{
159+
return ProgrammaticSaveAs();
160+
}
161+
}
162+
}
163+
return false;
164+
}
165+
166+
ScenarioSaveAs::~ScenarioSaveAs()
167+
{
168+
if (m_webView2Experimental25)
169+
{
170+
m_webView2Experimental25->remove_SaveAsUIShowing(m_saveAsUIShowingToken);
171+
}
172+
}
173+
174+
static INT_PTR CALLBACK DlgProcStatic(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
175+
{
176+
auto self = (SaveAsDialog*)GetWindowLongPtr(hDlg, GWLP_USERDATA);
177+
switch (message)
178+
{
179+
case WM_INITDIALOG:
180+
{
181+
self = (SaveAsDialog*)lParam;
182+
SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)self);
183+
HWND hwndList = GetDlgItem(hDlg, IDC_SAVE_AS_KIND);
184+
for (COREWEBVIEW2_SAVE_AS_KIND kind : self->kinds)
185+
{
186+
SendMessage(hwndList, CB_ADDSTRING, kind, (LPARAM)saveAsKindString[kind].c_str());
187+
SendMessage(hwndList, CB_SETITEMDATA, kind, (LPARAM)kind);
188+
}
189+
SendMessage(hwndList, CB_SETCURSEL, 0, 0);
190+
return (INT_PTR)TRUE;
191+
}
192+
case WM_COMMAND:
193+
{
194+
if (LOWORD(wParam) == IDOK)
195+
{
196+
HWND hwndList = GetDlgItem(hDlg, IDC_SAVE_AS_KIND);
197+
198+
wchar_t path[MAX_PATH] = {};
199+
int length = GetWindowTextLength(GetDlgItem(hDlg, IDC_EDIT_SAVE_AS_DIRECTORY)) +
200+
GetWindowTextLength(GetDlgItem(hDlg, IDC_EDIT_SAVE_AS_FILENAME));
201+
wchar_t directory[MAX_PATH] = {};
202+
GetDlgItemText(hDlg, IDC_EDIT_SAVE_AS_DIRECTORY, directory, length + 1);
203+
wchar_t filename[MAX_PATH] = {};
204+
GetDlgItemText(hDlg, IDC_EDIT_SAVE_AS_FILENAME, filename, length + 1);
205+
PathCombineW(path, directory, filename);
206+
self->path = path;
207+
208+
self->allowReplace = IsDlgButtonChecked(hDlg, IDC_CHECK_SAVE_AS_ALLOW_REPLACE);
209+
210+
int index = (int)SendMessage(hwndList, CB_GETCURSEL, 0, 0);
211+
self->selectedKind =
212+
(COREWEBVIEW2_SAVE_AS_KIND)SendMessage(hwndList, CB_GETITEMDATA, index, 0);
213+
214+
self->confirmed = true;
215+
}
216+
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
217+
{
218+
EndDialog(hDlg, LOWORD(wParam));
219+
return (INT_PTR)TRUE;
220+
}
221+
break;
222+
}
223+
case WM_NCDESTROY:
224+
SetWindowLongPtr(hDlg, GWLP_USERDATA, NULL);
225+
return (INT_PTR)TRUE;
226+
}
227+
return (INT_PTR)FALSE;
228+
}
229+
230+
SaveAsDialog::SaveAsDialog(HWND parent, std::initializer_list<COREWEBVIEW2_SAVE_AS_KIND> kinds)
231+
: kinds(kinds)
232+
{
233+
DialogBoxParam(
234+
g_hInstance, MAKEINTRESOURCE(IDD_SAVE_CONTENT_AS), parent, DlgProcStatic, (LPARAM)this);
235+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (C) Microsoft Corporation. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "stdafx.h"
6+
7+
#include <string>
8+
9+
#include "AppWindow.h"
10+
#include "ComponentBase.h"
11+
12+
class ScenarioSaveAs : public ComponentBase
13+
{
14+
public:
15+
ScenarioSaveAs(AppWindow* appWindow);
16+
bool ProgrammaticSaveAs();
17+
bool ToggleSilent();
18+
bool HandleWindowMessage(
19+
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* result) override;
20+
21+
private:
22+
~ScenarioSaveAs() override;
23+
AppWindow* m_appWindow = nullptr;
24+
wil::com_ptr<ICoreWebView2> m_webView;
25+
wil::com_ptr<ICoreWebView2Experimental25> m_webView2Experimental25;
26+
EventRegistrationToken m_saveAsUIShowingToken = {};
27+
bool m_silentSaveAs = false;
28+
};
29+
30+
struct SaveAsDialog
31+
{
32+
SaveAsDialog(HWND parent, std::initializer_list<COREWEBVIEW2_SAVE_AS_KIND> kinds);
33+
34+
std::initializer_list<COREWEBVIEW2_SAVE_AS_KIND> kinds;
35+
std::wstring path;
36+
bool allowReplace = false;
37+
COREWEBVIEW2_SAVE_AS_KIND selectedKind = COREWEBVIEW2_SAVE_AS_KIND_DEFAULT;
38+
bool confirmed = false;
39+
};

SampleApps/WebView2APISample/ScenarioSaveAsStaging.cpp

Lines changed: 0 additions & 16 deletions
This file was deleted.

SampleApps/WebView2APISample/ScenarioSaveAsStaging.h

Lines changed: 0 additions & 10 deletions
This file was deleted.

SampleApps/WebView2APISample/ViewComponent.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ ViewComponent::ViewComponent(
7676
// the html be the WebView2 logo. We do this by making
7777
// the background color transparent so the WebView2 logo in the AppWindow
7878
// shows through.
79-
COREWEBVIEW2_COLOR transparentColor = { 0, 255, 255, 255 };
79+
COREWEBVIEW2_COLOR transparentColor = {0, 0, 0, 0};
8080
wil::com_ptr<ICoreWebView2Controller2> controller2 =
8181
m_controller.query<ICoreWebView2Controller2>();
8282
// Save the previous background color to restore when navigating away.
@@ -261,7 +261,7 @@ bool ViewComponent::HandleWindowMessage(
261261
SetBackgroundColor(RGB(0, 0, 255), false);
262262
return true;
263263
case IDM_BACKGROUNDCOLOR_TRANSPARENT:
264-
SetBackgroundColor(RGB(255, 255, 255), true);
264+
SetBackgroundColor(RGB(0, 0, 0), true);
265265
return true;
266266
case IDM_ZOOM_05:
267267
SetZoomFactor(0.5f);

0 commit comments

Comments
 (0)