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 " pch.h"
6+
7+ #include " App.h"
8+ #include " AppWindow.h"
9+ #include " CheckFailure.h"
10+ #include " CompositionHost.h"
11+ #include < WinUser.h>
12+
13+ static constexpr LPCWSTR s_subFolder = nullptr ;
14+ static constexpr WCHAR c_samplePath[] = L" WebView2SamplePage.html" ;
15+
16+ AppWindow::AppWindow () : m_winComp(std::make_unique<CompositionHost>())
17+ {
18+ WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
19+ CHECK_FAILURE (CoInitializeEx (NULL , COINIT_APARTMENTTHREADED));
20+ LoadStringW (hInst, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
21+
22+ // Perform application initialization:
23+ m_mainWindow = CreateWindowW (
24+ GetWindowClass (), szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0 , CW_USEDEFAULT, 0 ,
25+ nullptr , nullptr , hInst, nullptr );
26+ SetWindowLongPtr (m_mainWindow, GWLP_USERDATA, (LONG_PTR)this );
27+ ShowWindow (m_mainWindow, nCmdShow);
28+ UpdateWindow (m_mainWindow);
29+
30+ m_sampleUri = GetLocalUri (c_samplePath);
31+ InitializeWebView ();
32+ }
33+
34+ // Register the Win32 window class for the app window.
35+ PCWSTR AppWindow::GetWindowClass ()
36+ {
37+ // Only do this once
38+ static PCWSTR windowClass = [] {
39+ static WCHAR windowClass[MAX_LOADSTRING];
40+ LoadStringW (hInst, IDC_WEBVIEW2SAMPLEWINCOMP, windowClass, MAX_LOADSTRING);
41+
42+ WNDCLASSEXW wcex;
43+
44+ wcex.cbSize = sizeof (WNDCLASSEX);
45+
46+ wcex.style = CS_HREDRAW | CS_VREDRAW;
47+ wcex.lpfnWndProc = WndProcStatic;
48+ wcex.cbClsExtra = 0 ;
49+ wcex.cbWndExtra = 0 ;
50+ wcex.hInstance = hInst;
51+ wcex.hIcon = LoadIcon (hInst, MAKEINTRESOURCE (IDI_WEBVIEW2SAMPLEWINCOMP));
52+ wcex.hCursor = LoadCursor (nullptr , IDC_ARROW);
53+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1 );
54+ wcex.lpszMenuName = MAKEINTRESOURCEW (IDC_WEBVIEW2SAMPLEWINCOMP);
55+ wcex.lpszClassName = windowClass;
56+ wcex.hIconSm = LoadIcon (wcex.hInstance , MAKEINTRESOURCE (IDI_SMALL));
57+
58+ RegisterClassExW (&wcex);
59+ return windowClass;
60+ }();
61+ return windowClass;
62+ }
63+
64+ LRESULT CALLBACK AppWindow::WndProcStatic (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
65+ {
66+
67+ if (auto app = (AppWindow*)GetWindowLongPtr (hWnd, GWLP_USERDATA))
68+ {
69+ if (app->HandleWindowMessage (hWnd, message, wParam, lParam))
70+ {
71+ return 0 ;
72+ }
73+ }
74+ return DefWindowProc (hWnd, message, wParam, lParam);
75+ }
76+
77+ bool AppWindow::HandleWindowMessage (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
78+ {
79+ if (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST)
80+ {
81+ m_winComp->OnMouseMessage (message, wParam, lParam);
82+ return true ;
83+ }
84+
85+ switch (message)
86+ {
87+ case WM_MOVE:
88+ {
89+ if (m_controller)
90+ {
91+ m_controller->NotifyParentWindowPositionChanged ();
92+ }
93+ return true ;
94+ }
95+ case WM_SIZE:
96+ {
97+ RECT availableBounds = {0 };
98+ GetClientRect (m_mainWindow, &availableBounds);
99+ m_winComp->SetBounds (availableBounds);
100+ return true ;
101+ }
102+ case WM_COMMAND:
103+ {
104+ int wmId = LOWORD (wParam);
105+ // Parse the menu selections:
106+ switch (wmId)
107+ {
108+ case IDM_ABOUT:
109+ DialogBox (hInst, MAKEINTRESOURCE (IDD_ABOUTBOX), hWnd, About);
110+ return true ;
111+ case IDM_EXIT:
112+ CloseAppWindow ();
113+ return true ;
114+ }
115+ break ;
116+ }
117+ case WM_PAINT:
118+ {
119+ PAINTSTRUCT ps;
120+ HDC hdc = BeginPaint (hWnd, &ps);
121+ EndPaint (hWnd, &ps);
122+ return true ;
123+ }
124+ case WM_DESTROY:
125+ PostQuitMessage (0 );
126+ return true ;
127+ }
128+ return false ;
129+ }
130+
131+ // Message handler for about box.
132+ INT_PTR CALLBACK AppWindow::About (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
133+ {
134+ UNREFERENCED_PARAMETER (lParam);
135+ switch (message)
136+ {
137+ case WM_INITDIALOG:
138+ return (INT_PTR)TRUE ;
139+ case WM_COMMAND:
140+ if (LOWORD (wParam) == IDOK || LOWORD (wParam) == IDCANCEL)
141+ {
142+ EndDialog (hDlg, LOWORD (wParam));
143+ return (INT_PTR)TRUE ;
144+ }
145+ break ;
146+ }
147+ return (INT_PTR)FALSE ;
148+ }
149+
150+ void AppWindow::InitializeWebView ()
151+ {
152+ auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();
153+ HRESULT hr = CreateCoreWebView2EnvironmentWithOptions (
154+ s_subFolder, nullptr , options.Get (),
155+ Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
156+ [this ](HRESULT result, ICoreWebView2Environment* environment) -> HRESULT {
157+ m_webViewEnvironment = environment;
158+ wil::com_ptr<ICoreWebView2Environment3>
159+ webViewEnvironment3 =
160+ m_webViewEnvironment.try_query <ICoreWebView2Environment3>();
161+
162+ if (webViewEnvironment3)
163+ {
164+ CHECK_FAILURE (
165+ webViewEnvironment3->CreateCoreWebView2CompositionController (
166+ m_mainWindow,
167+ Callback<
168+ ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler>(
169+ this , &AppWindow::OnCreateCoreWebView2ControllerCompleted)
170+ .Get ()));
171+ }
172+ return S_OK;
173+ })
174+ .Get ());
175+ assert (SUCCEEDED (hr));
176+ }
177+
178+ HRESULT AppWindow::OnCreateCoreWebView2ControllerCompleted (
179+ HRESULT result, ICoreWebView2CompositionController* compositionController)
180+ {
181+ if (result == S_OK)
182+ {
183+ m_compositionController = compositionController;
184+ CHECK_FAILURE (m_compositionController->QueryInterface (IID_PPV_ARGS (&m_controller)));
185+ CHECK_FAILURE (m_controller->get_CoreWebView2 (&m_webView));
186+ m_controller->put_IsVisible (true );
187+ m_webView->Navigate (m_sampleUri.c_str ());
188+ }
189+ else
190+ {
191+ ShowFailure (result, L" Failed to create webview" );
192+ }
193+ m_winComp->Initialize (this );
194+ return S_OK;
195+ }
196+
197+ void AppWindow::CloseWebView ()
198+ {
199+ if (m_controller)
200+ {
201+ m_controller->Close ();
202+ m_controller = nullptr ;
203+ m_webView = nullptr ;
204+ }
205+ m_webViewEnvironment = nullptr ;
206+ }
207+
208+ void AppWindow::CloseAppWindow ()
209+ {
210+ CloseWebView ();
211+ DestroyWindow (m_mainWindow);
212+ }
213+
214+ std::wstring AppWindow::GetLocalUri (std::wstring relativePath)
215+ {
216+ std::wstring path = GetLocalPath (relativePath, false );
217+
218+ wil::com_ptr<IUri> uri;
219+ CHECK_FAILURE (CreateUri (path.c_str (), Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0 , &uri));
220+
221+ wil::unique_bstr uriBstr;
222+ CHECK_FAILURE (uri->GetAbsoluteUri (&uriBstr));
223+ return std::wstring (uriBstr.get ());
224+ }
225+
226+ std::wstring AppWindow::GetLocalPath (std::wstring relativePath, bool keep_exe_path)
227+ {
228+ WCHAR rawPath[MAX_PATH];
229+ GetModuleFileNameW (hInst, rawPath, MAX_PATH);
230+ std::wstring path (rawPath);
231+ if (keep_exe_path)
232+ {
233+ path.append (relativePath);
234+ }
235+ else
236+ {
237+ std::size_t index = path.find_last_of (L" \\ " ) + 1 ;
238+ path.replace (index, path.length (), relativePath);
239+ }
240+ return path;
241+ }
0 commit comments