Skip to content

Commit 7b436f9

Browse files
committed
Update sample app as part of 12/09 SDK release
1 parent 3b0d465 commit 7b436f9

14 files changed

+751
-72
lines changed

WebView2APISample/AppWindow.cpp

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "Resource.h"
1818
#include "ScenarioAddRemoteObject.h"
1919
#include "ScenarioWebMessage.h"
20+
#include "ScenarioWebViewEventMonitor.h"
2021
#include "ScriptComponent.h"
2122
#include "SettingsComponent.h"
2223
#include "ViewComponent.h"
@@ -29,7 +30,8 @@ static constexpr UINT s_runAsyncWindowMessage = WM_APP;
2930
static thread_local size_t s_appInstances = 0;
3031

3132
// Creates a new window which is a copy of the entire app, but on the same thread.
32-
AppWindow::AppWindow(std::wstring initialUri) : m_initialUri(initialUri)
33+
AppWindow::AppWindow(std::wstring initialUri, std::function<void()> webviewCreatedCallback)
34+
: m_initialUri(initialUri), m_onWebViewFirstInitialized(webviewCreatedCallback)
3335
{
3436
++s_appInstances;
3537

@@ -222,6 +224,11 @@ bool AppWindow::ExecuteWebViewCommands(WPARAM wParam, LPARAM lParam)
222224
NewComponent<ScenarioAddRemoteObject>(this);
223225
return true;
224226
}
227+
case IDM_SCENARIO_WEB_VIEW_EVENT_MONITOR:
228+
{
229+
NewComponent<ScenarioWebViewEventMonitor>(this);
230+
return true;
231+
}
225232
}
226233
return false;
227234
}
@@ -250,6 +257,19 @@ bool AppWindow::ExecuteAppCommands(WPARAM wParam, LPARAM lParam)
250257
case IDM_REINIT_INSTALLED:
251258
InitializeWebView(kUseInstalledBrowser);
252259
return true;
260+
case IDM_REINIT_WINDOWED:
261+
InitializeWebView(kDefaultOption);
262+
return true;
263+
case IDM_TOGGLE_FULLSCREEN_ALLOWED:
264+
{
265+
m_fullScreenAllowed = !m_fullScreenAllowed;
266+
MessageBox(nullptr,
267+
(std::wstring(L"Fullscreen is now ") +
268+
(m_fullScreenAllowed ? L"allowed" : L"disallowed"))
269+
.c_str(),
270+
L"", MB_OK);
271+
return true;
272+
}
253273
case IDM_NEW_WINDOW:
254274
new AppWindow();
255275
return true;
@@ -407,8 +427,7 @@ void AppWindow::ReinitializeWebView()
407427
// Save the settings component from being deleted when the WebView is closed, so we can
408428
// copy its properties to the next settings component.
409429
m_oldSettingsComponent = MoveComponent<SettingsComponent>();
410-
// Workaround for Edge Bug 23006983
411-
RunAsync([this] { InitializeWebView(m_lastUsedInitFlags); });
430+
InitializeWebView(m_lastUsedInitFlags);
412431
}
413432

414433
void AppWindow::ReinitializeWebViewWithNewBrowser()
@@ -470,6 +489,29 @@ void AppWindow::RestartApp()
470489

471490
void AppWindow::RegisterEventHandlers()
472491
{
492+
//! [ContainsFullScreenElementChanged]
493+
// Register a handler for the ContainsFullScreenChanged event.
494+
CHECK_FAILURE(m_webView->add_ContainsFullScreenElementChanged(
495+
Callback<IWebView2ContainsFullScreenElementChangedEventHandler>(
496+
[this](IWebView2WebView5* sender, IUnknown* args) -> HRESULT {
497+
if (m_fullScreenAllowed)
498+
{
499+
CHECK_FAILURE(sender->get_ContainsFullScreenElement(&m_containsFullscreenElement));
500+
if (m_containsFullscreenElement)
501+
{
502+
EnterFullScreen();
503+
}
504+
else
505+
{
506+
ExitFullScreen();
507+
}
508+
}
509+
return S_OK;
510+
})
511+
.Get(),
512+
nullptr));
513+
//! [ContainsFullScreenElementChanged]
514+
473515
//! [NewWindowRequested]
474516
// Register a handler for the NewWindowRequested event.
475517
// This handler will defer the event, create a new app window, and then once the
@@ -491,7 +533,7 @@ void AppWindow::RegisterEventHandlers()
491533
return S_OK;
492534
})
493535
.Get(),
494-
&m_newWindowRequestedToken));
536+
nullptr));
495537
//! [NewWindowRequested]
496538

497539
//! [NewVersionAvailable]
@@ -509,12 +551,15 @@ void AppWindow::RegisterEventHandlers()
509551
message += L"\n\nVersion number: ";
510552
message += newVersion.get();
511553
message += L"\n\n";
512-
message += L"Do you want to restart the app? \n\n";
513-
message += L"Click No if you only want to re-create the webviews. \n";
514-
message += L"Click Cancel for no action. \n";
515-
554+
if (m_webView)
555+
{
556+
message += L"Do you want to restart the app? \n\n";
557+
message += L"Click No if you only want to re-create the webviews. \n";
558+
message += L"Click Cancel for no action. \n";
559+
}
516560
int response = MessageBox(
517-
m_mainWindow, message.c_str(), L"New available version", MB_YESNOCANCEL);
561+
m_mainWindow, message.c_str(), L"New available version",
562+
m_webView ? MB_YESNOCANCEL : MB_OK);
518563

519564
if (response == IDYES)
520565
{
@@ -532,7 +577,7 @@ void AppWindow::RegisterEventHandlers()
532577
return S_OK;
533578
})
534579
.Get(),
535-
&m_newVersionAvailableToken));
580+
nullptr));
536581
//! [NewVersionAvailable]
537582
}
538583

@@ -541,7 +586,12 @@ void AppWindow::ResizeEverything()
541586
{
542587
RECT availableBounds = {0};
543588
GetClientRect(m_mainWindow, &availableBounds);
589+
590+
if (!m_containsFullscreenElement)
591+
{
544592
availableBounds = m_toolbar.Resize(availableBounds);
593+
}
594+
545595
if (auto view = GetComponent<ViewComponent>())
546596
{
547597
view->SetBounds(availableBounds);
@@ -643,3 +693,33 @@ void AppWindow::RunAsync(std::function<void()> callback)
643693
auto* task = new std::function<void()>(callback);
644694
PostMessage(m_mainWindow, s_runAsyncWindowMessage, reinterpret_cast<WPARAM>(task), 0);
645695
}
696+
697+
void AppWindow::EnterFullScreen()
698+
{
699+
DWORD style = GetWindowLong(m_mainWindow, GWL_STYLE);
700+
MONITORINFO monitor_info = {sizeof(monitor_info)};
701+
m_hMenu = ::GetMenu(m_mainWindow);
702+
::SetMenu(m_mainWindow, nullptr);
703+
if (GetWindowPlacement(m_mainWindow, &m_previousPlacement) &&
704+
GetMonitorInfo(
705+
MonitorFromWindow(m_mainWindow, MONITOR_DEFAULTTOPRIMARY), &monitor_info))
706+
{
707+
SetWindowLong(m_mainWindow, GWL_STYLE, style & ~WS_OVERLAPPEDWINDOW);
708+
SetWindowPos(
709+
m_mainWindow, HWND_TOP, monitor_info.rcMonitor.left, monitor_info.rcMonitor.top,
710+
monitor_info.rcMonitor.right - monitor_info.rcMonitor.left,
711+
monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top,
712+
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
713+
}
714+
}
715+
716+
void AppWindow::ExitFullScreen()
717+
{
718+
DWORD style = GetWindowLong(m_mainWindow, GWL_STYLE);
719+
::SetMenu(m_mainWindow, m_hMenu);
720+
SetWindowLong(m_mainWindow, GWL_STYLE, style | WS_OVERLAPPEDWINDOW);
721+
SetWindowPlacement(m_mainWindow, &m_previousPlacement);
722+
SetWindowPos(
723+
m_mainWindow, NULL, 0, 0, 0, 0,
724+
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
725+
}

WebView2APISample/AppWindow.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ class SettingsComponent;
2020
class AppWindow
2121
{
2222
public:
23-
AppWindow(std::wstring initialUri = L"https://www.bing.com/");
23+
AppWindow(std::wstring initialUri = L"https://www.bing.com/",
24+
std::function<void()> webviewCreatedCallback = nullptr);
2425

25-
IWebView2WebView4* GetWebView()
26+
IWebView2WebView5* GetWebView()
2627
{
2728
return m_webView.get();
2829
}
@@ -89,9 +90,7 @@ class AppWindow
8990
// be reinitialized along with it. Everything here is undefined when
9091
// m_webView is null.
9192
wil::com_ptr<IWebView2Environment3> m_webViewEnvironment;
92-
wil::com_ptr<IWebView2WebView4> m_webView;
93-
EventRegistrationToken m_newWindowRequestedToken = {};
94-
EventRegistrationToken m_newVersionAvailableToken = {};
93+
wil::com_ptr<IWebView2WebView5> m_webView;
9594

9695
// All components are deleted when the WebView is closed.
9796
std::vector<std::unique_ptr<ComponentBase>> m_components;
@@ -100,6 +99,14 @@ class AppWindow
10099
// a new WebView based on the settings of the old one.
101100
InitializeWebViewFlags m_lastUsedInitFlags;
102101
std::unique_ptr<SettingsComponent> m_oldSettingsComponent;
102+
103+
// Fullscreen related code
104+
WINDOWPLACEMENT m_previousPlacement;
105+
HMENU m_hMenu;
106+
BOOL m_containsFullscreenElement;
107+
bool m_fullScreenAllowed = true;
108+
void EnterFullScreen();
109+
void ExitFullScreen();
103110
};
104111

105112
template <class ComponentType, class... Args> void AppWindow::NewComponent(Args&&... args)

WebView2APISample/ControlComponent.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class ControlComponent : public ComponentBase
3636

3737
private:
3838
AppWindow* m_appWindow;
39-
wil::com_ptr<IWebView2WebView4> m_webView;
39+
wil::com_ptr<IWebView2WebView5> m_webView;
4040
Toolbar* m_toolbar;
4141

4242
std::vector<std::pair<HWND, WNDPROC>> m_tabbableWindows;

WebView2APISample/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This is a hybrid application built with the [Microsoft Edge WebView2](https://docs.microsoft.com/en-us/microsoft-edge/hosting/webview2) control.
44

5-
![alt text](documentation/Screenshots/Sample-App-Screenshot.png)
5+
![alt text](documentation/Screenshots/Sample-App-Screenshot.PNG)
66

77

88
The WebView2APISample is an example of an application that embeds a WebView within a Win32 native application. It is built as a Win32 [Visual Studio 2019](https://visualstudio.microsoft.com/vs/) project and makes use of both C++ and HTML/CSS/JavaScript in the WebView2 environment.
@@ -41,7 +41,7 @@ This hybrid approach allows you to create and iterate faster using web technolog
4141

4242
Both of these parts of the Sample App are displayed in the image below:
4343

44-
![alt text](documentation/Screenshots/Sample-App-Layout-Diagram.png)
44+
![alt text](documentation/Screenshots/Sample-App-Layout-Diagram.PNG)
4545
1. Section One: The top part of the Sample App is a Win32 component written in C++. This part of the application takes in UI inputs from the user and uses them to control the WebView.
4646

4747
2. Section Two: The main part of the Sample App is a WebView that can be repurposed using standard web technologies (HTML/CSS/JavaScript). It can be navigated to websites or local content.
@@ -74,7 +74,7 @@ This component handles commands from the View menu, and any functionality relate
7474
#### 8. ScenarioWebMessage.cpp and ScenarioWebMessage.html
7575
This component is created when you select the Scenario/Web Messaging menu item. It implements an example application with a C++ part and an HTML+JavaScript part, which communicate with each other by asynchronously posting and recieving messages.
7676

77-
![alt text](documentation/Screenshots/Sample-App-WebMessaging-Screenshot.png)
77+
![alt text](documentation/Screenshots/Sample-App-WebMessaging-Screenshot.PNG)
7878

7979
#### 9. ScenarioAddRemoteObject.cpp and ScenarioAddRemoteObject.html
8080
This component is created when you select the Scenario/Remote Objects menu item. It demonstrates communication between the native app and the HTML webpage by means of remote object injection. The interface of the remote object is declared in RemoteObjectSample.idl, and the object itself is implemented in RemoteObjectSampleImpl.cpp.
@@ -180,7 +180,7 @@ First, navigate to the ScenarioWebMessage application within the Sample App, usi
180180

181181
The WebView should display a simple webpage titled: "WebMessage sample page". The code for this page can be found in the ScenarioWebMessage.html file.
182182

183-
![alt text](documentation/Screenshots/Sample-App-WebMessaging-Screenshot.png)
183+
![alt text](documentation/Screenshots/Sample-App-WebMessaging-Screenshot.PNG)
184184

185185
To better understand ScenarioWebMessage functionality, you can either follow the instructions on the page or the steps detailed below.
186186

WebView2APISample/ScenarioAddRemoteObject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class ScenarioAddRemoteObject : public ComponentBase
2020

2121
private:
2222
AppWindow* m_appWindow = nullptr;
23-
wil::com_ptr<IWebView2WebView4> m_webView;
23+
wil::com_ptr<IWebView2WebView5> m_webView;
2424
wil::com_ptr<RemoteObjectSample> m_remoteObject;
2525

2626
EventRegistrationToken m_navigationStartingToken = {};

0 commit comments

Comments
 (0)