Skip to content

Commit f5a7840

Browse files
committed
Adding WebView2 API Sample with updates to documentation
1 parent a9581f9 commit f5a7840

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+5402
-3
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ Start with the [Microsoft Edge WebView2 getting-started guide](https://docs.micr
88

99
This Sample is found within the GettingStartedGuide directory.
1010

11-
## 2. WebView2 Browser Example
11+
## 2. WebView2 API Sample
1212

13-
Follow the [WebView2Browser guide](https://github.com/MicrosoftEdge/WebView2Browser) to learn how to build an application that utilizes multiple WebViews.
13+
This Sample is found within the [WebView2APISample](WebView2APISample) directory.
1414

15-
Clone the project by running `git clone https://github.com/MicrosoftEdge/WebView2Browser.git` to get started.
15+
The Microsoft Edge WebView2APISample is a comprehensive example of our SDK's capabilities. As we add more functionality, we will update the API Sample.
1616

17+
## 3. WebView2 Browser Example
1718

19+
Follow the [WebView2Browser guide](https://github.com/MicrosoftEdge/WebView2Browser) to learn how to build an application that utilizes multiple WebViews.
20+
21+
Clone the project by running `git clone https://github.com/MicrosoftEdge/WebView2Browser.git` to get started.
1822

WebView2APISample/.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Debug/
2+
Release/
3+
S Debug/
4+
S Release/
5+
ipch/
6+
x64/
7+
x86/
8+
.vs/
9+
packages/
10+
11+
# Override root .gitignore to ensure we pick up changes for the sample app
12+
!*.sln
13+
!*.vcxproj
14+
!*.vcxproj.filters
15+
16+
# Ignore the binary generated version of the resource (.rc) file
17+
*.aps
18+
19+
# Ignore files generated by midl
20+
/RemoteObjectSample_h.h
21+
/RemoteObjectSample_i.c

WebView2APISample/App.cpp

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
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 "App.h"
8+
9+
#include <map>
10+
#include <shellscalingapi.h>
11+
#include <shobjidl.h>
12+
#include <string.h>
13+
#include <vector>
14+
15+
#include "AppWindow.h"
16+
17+
HINSTANCE g_hInstance;
18+
int g_nCmdShow;
19+
bool g_autoTabHandle = true;
20+
21+
static std::map<DWORD, HANDLE> s_threads;
22+
23+
static int RunMessagePump();
24+
static DWORD WINAPI ThreadProc(void* pvParam);
25+
static void WaitForOtherThreads();
26+
27+
int APIENTRY wWinMain(HINSTANCE hInstance,
28+
HINSTANCE hPrevInstance,
29+
PWSTR lpCmdLine,
30+
int nCmdShow)
31+
{
32+
g_hInstance = hInstance;
33+
UNREFERENCED_PARAMETER(hPrevInstance);
34+
g_nCmdShow = nCmdShow;
35+
36+
// Default DPI awareness to PerMonitorV2. The commandline parameters can
37+
// override this.
38+
DPI_AWARENESS_CONTEXT dpiAwarenessContext =
39+
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
40+
// Same but for older OS versions that don't support per-monitor v2
41+
PROCESS_DPI_AWARENESS oldDpiAwareness = PROCESS_PER_MONITOR_DPI_AWARE;
42+
std::wstring appId(L"EBWebView.SampleApp");
43+
std::wstring initialUri(L"https://www.bing.com");
44+
45+
if (lpCmdLine && lpCmdLine[0])
46+
{
47+
bool commandLineError = false;
48+
49+
PWSTR nextParam = lpCmdLine;
50+
51+
if (nextParam[0] == L'-')
52+
{
53+
++nextParam;
54+
if (nextParam[0] == L'-')
55+
{
56+
++nextParam;
57+
}
58+
if (_wcsnicmp(nextParam, L"dpiunaware", ARRAYSIZE(L"dpiunaware") - 1) ==
59+
0)
60+
{
61+
dpiAwarenessContext = DPI_AWARENESS_CONTEXT_UNAWARE;
62+
oldDpiAwareness = PROCESS_DPI_UNAWARE;
63+
}
64+
else if (_wcsnicmp(nextParam, L"dpisystemaware",
65+
ARRAYSIZE(L"dpisystemaware") - 1) == 0)
66+
{
67+
dpiAwarenessContext = DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
68+
oldDpiAwareness = PROCESS_SYSTEM_DPI_AWARE;
69+
}
70+
else if (_wcsnicmp(nextParam, L"dpipermonitorawarev2",
71+
ARRAYSIZE(L"dpipermonitorawarev2") - 1) == 0)
72+
{
73+
dpiAwarenessContext = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
74+
oldDpiAwareness = PROCESS_PER_MONITOR_DPI_AWARE;
75+
}
76+
else if (_wcsnicmp(nextParam, L"dpipermonitoraware",
77+
ARRAYSIZE(L"dpipermonitoraware") - 1) == 0)
78+
{
79+
dpiAwarenessContext = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
80+
oldDpiAwareness = PROCESS_PER_MONITOR_DPI_AWARE;
81+
}
82+
else if (_wcsnicmp(nextParam, L"noinitialnavigation",
83+
ARRAYSIZE(L"noinitialnavigation") - 1) == 0)
84+
{
85+
initialUri = L"";
86+
}
87+
else if (_wcsnicmp(nextParam, L"appid=",
88+
ARRAYSIZE(L"appid=") - 1) == 0)
89+
{
90+
PWSTR appidStart = nextParam + ARRAYSIZE(L"appid=");
91+
size_t len = 0;
92+
while (appidStart[len] && (appidStart[len] != ' '))
93+
++len;
94+
appId = std::wstring(appidStart, len);
95+
}
96+
else if (_wcsnicmp(nextParam, L"initialUri=",
97+
ARRAYSIZE(L"initialUri=") - 1) == 0)
98+
{
99+
PWSTR uriStart = nextParam + ARRAYSIZE(L"initialUri=") - 1;
100+
size_t len = 0;
101+
while (uriStart[len] && (uriStart[len] != ' '))
102+
++len;
103+
initialUri = std::wstring(uriStart, len);
104+
}
105+
else
106+
{
107+
// --edge-webview-switches is a supported switch to pass addtional
108+
// command line switches to WebView's browser process.
109+
// For example, adding
110+
// --edge-webview-switches="--remote-debugging-port=9222"
111+
// enables remote debugging for webview.
112+
// And adding
113+
// --edge-webview-switches="--auto-open-devtools-for-tabs"
114+
// causes dev tools to open automatically for the WebView.
115+
commandLineError =
116+
(wcsncmp(nextParam, L"edge-webview-switches",
117+
ARRAYSIZE(L"edge-webview-switches") - 1) != 0) &&
118+
(wcsncmp(nextParam, L"restore",
119+
ARRAYSIZE(L"restore") - 1) != 0);
120+
}
121+
}
122+
else
123+
{
124+
commandLineError = true;
125+
}
126+
127+
if (commandLineError)
128+
{
129+
MessageBox(nullptr,
130+
L"Valid command line "
131+
L"parameters:\n\t-DPIUnaware\n\t-DPISystemAware\n\t-"
132+
L"DPIPerMonitorAware\n\t-DPIPerMonitorAwareV2",
133+
L"Command Line Parameters", MB_OK);
134+
}
135+
}
136+
137+
SetCurrentProcessExplicitAppUserModelID(appId.c_str());
138+
139+
// Call the latest DPI awareness function possible
140+
HMODULE user32 = LoadLibraryA("User32.dll");
141+
auto func = reinterpret_cast<decltype(&SetProcessDpiAwarenessContext)>(
142+
GetProcAddress(user32, "SetProcessDpiAwarenessContext"));
143+
if (func)
144+
{
145+
// Windows 10 1703+: SetProcessDpiAwarenessContext
146+
func(dpiAwarenessContext);
147+
}
148+
else {
149+
HMODULE shcore = LoadLibraryA("Shcore.dll");
150+
auto func = reinterpret_cast<decltype(&SetProcessDpiAwareness)>(
151+
GetProcAddress(shcore, "SetProcessDpiAwareness"));
152+
if (func)
153+
{
154+
// Windows 8.1+: SetProcessDpiAwareness
155+
func(oldDpiAwareness);
156+
}
157+
else if (dpiAwarenessContext != DPI_AWARENESS_CONTEXT_UNAWARE)
158+
{
159+
// Windows 7+: SetProcessDPIAware
160+
SetProcessDPIAware();
161+
}
162+
}
163+
164+
new AppWindow(initialUri);
165+
166+
int retVal = RunMessagePump();
167+
168+
WaitForOtherThreads();
169+
170+
return retVal;
171+
}
172+
173+
// Run the message pump for one thread.
174+
static int RunMessagePump()
175+
{
176+
HACCEL hAccelTable =
177+
LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDC_WEBVIEW2APISAMPLE));
178+
179+
MSG msg;
180+
181+
// Main message loop:
182+
//! [MoveFocus0]
183+
while (GetMessage(&msg, nullptr, 0, 0))
184+
{
185+
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
186+
{
187+
// Calling IsDialogMessage handles Tab traversal automatically. If the
188+
// app wants the platform to auto handle tab, then call IsDialogMessage
189+
// before calling TranslateMessage/DispatchMessage. If the app wants to
190+
// handle tabbing itself, then skip calling IsDialogMessage and call
191+
// TranslateMessage/DispatchMessage directly.
192+
if (!g_autoTabHandle || !IsDialogMessage(GetAncestor(msg.hwnd, GA_ROOT), &msg))
193+
{
194+
TranslateMessage(&msg);
195+
DispatchMessage(&msg);
196+
}
197+
}
198+
}
199+
//! [MoveFocus0]
200+
201+
DWORD threadId = GetCurrentThreadId();
202+
auto it = s_threads.find(threadId);
203+
if (it != s_threads.end())
204+
{
205+
CloseHandle(it->second);
206+
s_threads.erase(threadId);
207+
}
208+
209+
return (int)msg.wParam;
210+
}
211+
212+
// Make a new thread.
213+
void CreateNewThread()
214+
{
215+
DWORD threadId;
216+
HANDLE thread = CreateThread(nullptr, 0, ThreadProc, nullptr,
217+
STACK_SIZE_PARAM_IS_A_RESERVATION, &threadId);
218+
s_threads.insert(std::pair<DWORD, HANDLE>(threadId, thread));
219+
}
220+
221+
// This function is the starting point for new threads. It will open a new app window.
222+
static DWORD WINAPI ThreadProc(void* pvParam)
223+
{
224+
new AppWindow();
225+
return RunMessagePump();
226+
}
227+
228+
// Called on the main thread. Wait for all other threads to complete before exiting.
229+
static void WaitForOtherThreads()
230+
{
231+
while (!s_threads.empty())
232+
{
233+
std::vector<HANDLE> threadHandles;
234+
for (auto it = s_threads.begin(); it != s_threads.end(); ++it)
235+
{
236+
threadHandles.push_back(it->second);
237+
}
238+
239+
HANDLE* handleArray = threadHandles.data();
240+
DWORD dwIndex = MsgWaitForMultipleObjects(
241+
static_cast<DWORD>(threadHandles.size()), threadHandles.data(), FALSE,
242+
INFINITE, QS_ALLEVENTS);
243+
244+
if (dwIndex == WAIT_OBJECT_0 + threadHandles.size())
245+
{
246+
MSG msg;
247+
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
248+
{
249+
TranslateMessage(&msg);
250+
DispatchMessage(&msg);
251+
}
252+
}
253+
}
254+
}

WebView2APISample/App.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
extern HINSTANCE g_hInstance;
8+
extern int g_nCmdShow;
9+
extern bool g_autoTabHandle;
10+
11+
void CreateNewThread();

0 commit comments

Comments
 (0)