comparison win/edge.cpp @ 2042:0d8b898b03e2

Win: Rewrite edge.cpp using C++ classes, EdgeBrowser and EdgeWebView. This fixes issues with the IWebView2WebView members being out of scope when I save and reload the pointer.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sun, 24 Nov 2019 21:01:46 +0000
parents 638be5b17715
children 82e5c998df2e
comparison
equal deleted inserted replaced
2041:638be5b17715 2042:0d8b898b03e2
20 #define _DW_HTML_DATA_RAW "_dw_edge_raw" 20 #define _DW_HTML_DATA_RAW "_dw_edge_raw"
21 21
22 extern "C" { 22 extern "C" {
23 23
24 /* Import the character conversion functions from dw.c */ 24 /* Import the character conversion functions from dw.c */
25 LPWSTR _myUTF8toWide(const char *utf8string, void *outbuf); 25 LPWSTR _myUTF8toWide(const char* utf8string, void* outbuf);
26 char *_myWideToUTF8(LPCWSTR widestring, void *outbuf); 26 char* _myWideToUTF8(LPCWSTR widestring, void* outbuf);
27 #define UTF8toWide(a) _myUTF8toWide(a, a ? _alloca(MultiByteToWideChar(CP_UTF8, 0, a, -1, NULL, 0) * sizeof(WCHAR)) : NULL) 27 #define UTF8toWide(a) _myUTF8toWide(a, a ? _alloca(MultiByteToWideChar(CP_UTF8, 0, a, -1, NULL, 0) * sizeof(WCHAR)) : NULL)
28 #define WideToUTF8(a) _myWideToUTF8(a, a ? _alloca(WideCharToMultiByte(CP_UTF8, 0, a, -1, NULL, 0, NULL, NULL)) : NULL) 28 #define WideToUTF8(a) _myWideToUTF8(a, a ? _alloca(WideCharToMultiByte(CP_UTF8, 0, a, -1, NULL, 0, NULL, NULL)) : NULL)
29 LRESULT CALLBACK _wndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2); 29 LRESULT CALLBACK _wndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2);
30 BOOL CALLBACK _free_window_memory(HWND handle, LPARAM lParam); 30 BOOL CALLBACK _free_window_memory(HWND handle, LPARAM lParam);
31 IWebView2Environment *DW_EDGE_ENV = NULL; 31 }
32 32
33 class EdgeBrowser
34 {
35 public:
36 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
37 BOOL Detect(VOID);
38 protected:
39 Microsoft::WRL::ComPtr<IWebView2Environment> Env;
40 };
41
42 class EdgeWebView
43 {
44 public:
45 VOID Action(int action);
46 int Raw(const char* string);
47 int URL(const char* url);
48 int JavascriptRun(const char* script, void* scriptdata);
49 VOID DoSize(VOID);
50 VOID Setup(HWND hwnd, IWebView2WebView* webview);
51 VOID Close(VOID);
52 protected:
53 HWND hWnd = nullptr;
54 Microsoft::WRL::ComPtr<IWebView2WebView> WebView;
55 };
56
57 LRESULT CALLBACK EdgeBrowser::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
58 {
59 switch (uMsg)
60 {
61 case WM_SIZE:
62 {
63 // Resize the browser object to fit the window
64 EdgeWebView *webview;
65
66 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
67 // we initially attached the browser object to this window.
68 webview = (EdgeWebView*)dw_window_get_data(hWnd, _DW_HTML_DATA_NAME);
69 // Resize WebView to fit the bounds of the parent window
70 if (webview)
71 webview->DoSize();
72 return(0);
73 }
74
75 case WM_PAINT:
76 {
77 PAINTSTRUCT ps;
78 HDC hdc = BeginPaint(hWnd, &ps);
79 EndPaint(hWnd, &ps);
80 return(0);
81 }
82
83 case WM_CREATE:
84 {
85 // Step 3 - Create a single WebView within the parent window
86 // Create a WebView, whose parent is the main window hWnd
87 Env->CreateWebView(hWnd, Callback<IWebView2CreateWebViewCompletedHandler>(
88 [hWnd](HRESULT result, IWebView2WebView* webview) -> HRESULT {
89 EdgeWebView* WebView = new EdgeWebView;
90
91 WebView->Setup(hWnd, webview);
92 dw_window_set_data(hWnd, _DW_HTML_DATA_NAME, DW_POINTER(WebView));
93
94 // Add a few settings for the webview
95 // this is a redundant demo step as they are the default settings values
96 IWebView2Settings* Settings;
97 webview->get_Settings(&Settings);
98 Settings->put_IsScriptEnabled(TRUE);
99 Settings->put_AreDefaultScriptDialogsEnabled(TRUE);
100 Settings->put_IsWebMessageEnabled(TRUE);
101
102 // Resize WebView to fit the bounds of the parent window
103 WebView->DoSize();
104
105 // Save the token, we might need to dw_window_set_data() this value
106 // for later use to remove the handlers
107 EventRegistrationToken token;
108
109 // Register a handler for the NavigationStarting event.
110 webview->add_NavigationStarting(
111 Callback<IWebView2NavigationStartingEventHandler>(
112 [hWnd](IWebView2WebView* sender,
113 IWebView2NavigationStartingEventArgs* args) -> HRESULT
114 {
115 LPWSTR uri;
116 sender->get_Source(&uri);
117
118 _wndproc(hWnd, WM_USER + 101, (WPARAM)DW_INT_TO_POINTER(DW_HTML_CHANGE_STARTED),
119 !wcscmp(uri, L"about:blank") ? (LPARAM)"" : (LPARAM)WideToUTF8((LPWSTR)uri));
120
121 return S_OK;
122 }).Get(), &token);
123
124 // Register a handler for the DocumentStateChanged event.
125 webview->add_DocumentStateChanged(
126 Callback<IWebView2DocumentStateChangedEventHandler>(
127 [hWnd](IWebView2WebView* sender,
128 IWebView2DocumentStateChangedEventArgs* args) -> HRESULT
129 {
130 LPWSTR uri;
131 sender->get_Source(&uri);
132
133 _wndproc(hWnd, WM_USER + 101, (WPARAM)DW_INT_TO_POINTER(DW_HTML_CHANGE_LOADING),
134 !wcscmp(uri, L"about:blank") ? (LPARAM)"" : (LPARAM)WideToUTF8((LPWSTR)uri));
135
136 return S_OK;
137 }).Get(), &token);
138
139 // Register a handler for the NavigationCompleted event.
140 webview->add_NavigationCompleted(
141 Callback<IWebView2NavigationCompletedEventHandler>(
142 [hWnd](IWebView2WebView* sender,
143 IWebView2NavigationCompletedEventArgs* args) -> HRESULT
144 {
145 LPWSTR uri;
146 sender->get_Source(&uri);
147
148 _wndproc(hWnd, WM_USER + 101, (WPARAM)DW_INT_TO_POINTER(DW_HTML_CHANGE_COMPLETE),
149 !wcscmp(uri, L"about:blank") ? (LPARAM)"" : (LPARAM)WideToUTF8((LPWSTR)uri));
150
151 return S_OK;
152 }).Get(), &token);
153
154 // Handle cached load requests due to delayed
155 // loading of the edge webview contexts
156 char *url = (char *)dw_window_get_data(hWnd, _DW_HTML_DATA_LOCATION);
157 if (url)
158 {
159 WebView->URL(url);
160 free((void*)url);
161 }
162 char *raw = (char *)dw_window_get_data(hWnd, _DW_HTML_DATA_RAW);
163 if (raw)
164 {
165 WebView->Raw(raw);
166 free((void*)raw);
167 }
168 return S_OK;
169 }).Get());
170 // Success
171 return(0);
172 }
173
174 case WM_DESTROY:
175 {
176 // Detach the browser object from this window, and free resources.
177 EdgeWebView *webview;
178
179 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
180 // we initially attached the browser object to this window.
181 webview = (EdgeWebView*)dw_window_get_data(hWnd, _DW_HTML_DATA_NAME);
182 if (webview)
183 {
184 dw_window_set_data(hWnd, _DW_HTML_DATA_NAME, NULL);
185 webview->Close();
186 delete webview;
187 }
188 _free_window_memory(hWnd, 0);
189 return(TRUE);
190 }
191 }
192
193 return(DefWindowProc(hWnd, uMsg, wParam, lParam));
194 }
195
196 VOID EdgeWebView::DoSize(VOID)
197 {
198 RECT bounds;
199
200 GetClientRect(hWnd, &bounds);
201 WebView->put_Bounds(bounds);
202 }
203
204 BOOL EdgeBrowser::Detect(VOID)
205 {
206 CreateWebView2EnvironmentWithDetails(nullptr, nullptr, nullptr,
207 Callback<IWebView2CreateWebView2EnvironmentCompletedHandler>(
208 [this](HRESULT result, IWebView2Environment* env) -> HRESULT {
209 // Successfully created Edge environment, return TRUE
210 Env = env;
211 return S_OK;
212 }).Get());
213 return Env ? TRUE : FALSE;
214 }
215
216 void EdgeWebView::Action(int action)
217 {
218 // We want to get the base address (ie, a pointer) to the IWebView2WebView object embedded within the browser
219 // object, so we can call some of the functions in the former's table.
220 if (WebView)
221 {
222 // Call the desired function
223 switch (action)
224 {
225 case DW_HTML_GOBACK:
226 {
227 // Call the IWebView2WebView object's GoBack function.
228 WebView->GoBack();
229 break;
230 }
231
232 case DW_HTML_GOFORWARD:
233 {
234 // Call the IWebView2WebView object's GoForward function.
235 WebView->GoForward();
236 break;
237 }
238
239 case DW_HTML_GOHOME:
240 {
241 // Call the IWebView2WebView object's GoHome function.
242 dw_html_url(hWnd, (char*)DW_HOME_URL);
243 break;
244 }
245
246 case DW_HTML_SEARCH:
247 {
248 // Call the IWebView2WebView object's GoSearch function.
249 //WebView->GoSearch();
250 break;
251 }
252
253 case DW_HTML_RELOAD:
254 {
255 // Call the IWebView2WebView object's Refresh function.
256 WebView->Reload();
257 }
258
259 case DW_HTML_STOP:
260 {
261 // Call the IWebView2WebView object's Stop function.
262 //WebView->Stop();
263 }
264 }
265 }
266 }
267
268 int EdgeWebView::Raw(const char* string)
269 {
270 if (WebView)
271 WebView->NavigateToString(UTF8toWide(string));
272 return DW_ERROR_NONE;
273 }
274
275 int EdgeWebView::URL(const char* url)
276 {
277 if (WebView)
278 WebView->Navigate(UTF8toWide(url));
279 return DW_ERROR_NONE;
280 }
281
282 int EdgeWebView::JavascriptRun(const char* script, void* scriptdata)
283 {
284 HWND thishwnd = hWnd;
285
286 if (WebView)
287 WebView->ExecuteScript(UTF8toWide(script),
288 Callback<IWebView2ExecuteScriptCompletedHandler>(
289 [thishwnd, scriptdata](HRESULT error, PCWSTR result) -> HRESULT
290 {
291 _wndproc(thishwnd, WM_USER + 100, (error == S_OK ? (WPARAM)WideToUTF8((LPWSTR)result) : NULL), (LPARAM)scriptdata);
292 return S_OK;
293 }).Get());
294 return DW_ERROR_NONE;
295 }
296
297 VOID EdgeWebView::Setup(HWND hwnd, IWebView2WebView* webview)
298 {
299 hWnd = hwnd;
300 WebView = webview;
301 }
302
303 VOID EdgeWebView::Close(VOID)
304 {
305 if (WebView)
306 WebView->Close();
307 }
308
309 EdgeBrowser *DW_EDGE = NULL;
310
311 extern "C" {
33 /******************************* dw_edge_detect() ************************** 312 /******************************* dw_edge_detect() **************************
34 * Attempts to create a temporary Edge (Chromium) browser context... 313 * Attempts to create a temporary Edge (Chromium) browser context...
35 * If we succeed return TRUE and use Edge for HTML windows. 314 * If we succeed return TRUE and use Edge for HTML windows.
36 * If it fails return FALSE and fall back to using embedded IE. 315 * If it fails return FALSE and fall back to using embedded IE.
37 */ 316 */
38 BOOL _dw_edge_detect(VOID) 317 BOOL _dw_edge_detect(VOID)
39 { 318 {
40 CreateWebView2EnvironmentWithDetails(nullptr, nullptr, nullptr, 319 DW_EDGE = new EdgeBrowser;
41 Callback<IWebView2CreateWebView2EnvironmentCompletedHandler>( 320 if (DW_EDGE)
42 [](HRESULT result, IWebView2Environment* env) -> HRESULT { 321 {
43 // Successfully created Edge environment, return TRUE 322 BOOL result = DW_EDGE->Detect();
44 DW_EDGE_ENV = env; 323 if (!result)
45 return S_OK; 324 {
46 }).Get()); 325 delete DW_EDGE;
47 return DW_EDGE_ENV ? TRUE : FALSE; 326 DW_EDGE = NULL;
327 }
328 return result;
329 }
330 return FALSE;
48 } 331 }
49 332
50 /******************************* dw_edge_action() ************************** 333 /******************************* dw_edge_action() **************************
51 * Implements the functionality of a "Back". "Forward", "Home", "Search", 334 * Implements the functionality of a "Back". "Forward", "Home", "Search",
52 * "Refresh", or "Stop" button. 335 * "Refresh", or "Stop" button.
61 * 5 = Stop the currently loading page. 344 * 5 = Stop the currently loading page.
62 */ 345 */
63 346
64 void _dw_edge_action(HWND hwnd, int action) 347 void _dw_edge_action(HWND hwnd, int action)
65 { 348 {
66 IWebView2WebView* webview; 349 EdgeWebView* webview = (EdgeWebView *)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME);
67 350 if (webview)
68 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when 351 webview->Action(action);
69 // we initially attached the browser object to this window.
70 webview = (IWebView2WebView*)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME);
71
72 // We want to get the base address (ie, a pointer) to the IWebView2WebView object embedded within the browser
73 // object, so we can call some of the functions in the former's table.
74 if (webview)
75 {
76 // Call the desired function
77 switch (action)
78 {
79 case DW_HTML_GOBACK:
80 {
81 // Call the IWebView2WebView object's GoBack function.
82 webview->GoBack();
83 break;
84 }
85
86 case DW_HTML_GOFORWARD:
87 {
88 // Call the IWebView2WebView object's GoForward function.
89 webview->GoForward();
90 break;
91 }
92
93 case DW_HTML_GOHOME:
94 {
95 // Call the IWebView2WebView object's GoHome function.
96 dw_html_url(hwnd, (char *)DW_HOME_URL);
97 break;
98 }
99
100 case DW_HTML_SEARCH:
101 {
102 // Call the IWebView2WebView object's GoSearch function.
103 //webview->GoSearch();
104 break;
105 }
106
107 case DW_HTML_RELOAD:
108 {
109 // Call the IWebView2WebView object's Refresh function.
110 webview->Reload();
111 }
112
113 case DW_HTML_STOP:
114 {
115 // Call the IWebView2WebView object's Stop function.
116 //webview->Stop();
117 }
118 }
119 }
120 } 352 }
121 353
122 /******************************* dw_edge_raw() **************************** 354 /******************************* dw_edge_raw() ****************************
123 * Takes a string containing some HTML BODY, and displays it in the specified 355 * Takes a string containing some HTML BODY, and displays it in the specified
124 * window. For example, perhaps you want to display the HTML text of... 356 * window. For example, perhaps you want to display the HTML text of...
130 * (NOTE: No <BODY></BODY> tags are required in the string). 362 * (NOTE: No <BODY></BODY> tags are required in the string).
131 * 363 *
132 * RETURNS: 0 if success, or non-zero if an error. 364 * RETURNS: 0 if success, or non-zero if an error.
133 */ 365 */
134 366
135 int _dw_edge_raw(HWND hwnd, const char *string) 367 int _dw_edge_raw(HWND hwnd, const char* string)
136 { 368 {
137 IWebView2WebView* webview; 369 EdgeWebView* webview = (EdgeWebView*)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME);
138 370 if (webview)
139 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when 371 return webview->Raw(string);
140 // we initially attached the browser object to this window.
141 webview = (IWebView2WebView*)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME);
142
143 if (webview)
144 webview->NavigateToString(UTF8toWide(string));
145 else 372 else
146 dw_window_set_data(hwnd, _DW_HTML_DATA_RAW, _wcsdup(UTF8toWide(string))); 373 dw_window_set_data(hwnd, _DW_HTML_DATA_RAW, strdup(string));
147 return DW_ERROR_NONE; 374 return DW_ERROR_NONE;
148 } 375 }
149 376
150 /******************************* dw_edge_url() **************************** 377 /******************************* dw_edge_url() ****************************
151 * Displays a URL, or HTML file on disk. 378 * Displays a URL, or HTML file on disk.
154 * url = Pointer to nul-terminated name of the URL/file. 381 * url = Pointer to nul-terminated name of the URL/file.
155 * 382 *
156 * RETURNS: 0 if success, or non-zero if an error. 383 * RETURNS: 0 if success, or non-zero if an error.
157 */ 384 */
158 385
159 int _dw_edge_url(HWND hwnd, const char *url) 386 int _dw_edge_url(HWND hwnd, const char* url)
160 { 387 {
161 IWebView2WebView* webview; 388 EdgeWebView* webview = (EdgeWebView*)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME);
162 389 if (webview)
163 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when 390 return webview->URL(url);
164 // we initially attached the browser object to this window.
165 webview = (IWebView2WebView*)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME);
166
167 if (webview)
168 webview->Navigate(UTF8toWide(url));
169 else 391 else
170 dw_window_set_data(hwnd, _DW_HTML_DATA_LOCATION, _wcsdup(UTF8toWide(url))); 392 dw_window_set_data(hwnd, _DW_HTML_DATA_LOCATION, strdup(url));
171 return DW_ERROR_NONE; 393 return DW_ERROR_NONE;
172 } 394 }
173 395
174 /******************************* dw_edge_javascript_run() **************************** 396 /******************************* dw_edge_javascript_run() ****************************
175 * Runs a javascript in the specified browser context. 397 * Runs a javascript in the specified browser context.
179 * scriptdata = Pointer to user data to be passed to the callback. 401 * scriptdata = Pointer to user data to be passed to the callback.
180 * 402 *
181 * RETURNS: 0 if success, or non-zero if an error. 403 * RETURNS: 0 if success, or non-zero if an error.
182 */ 404 */
183 405
184 int _dw_edge_javascript_run(HWND hwnd, const char *script, void *scriptdata) 406 int _dw_edge_javascript_run(HWND hwnd, const char* script, void* scriptdata)
185 { 407 {
186 IWebView2WebView* webview; 408 EdgeWebView* webview = (EdgeWebView*)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME);
187 409 if (webview)
188 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when 410 return webview->JavascriptRun(script, scriptdata);
189 // we initially attached the browser object to this window. 411 return DW_ERROR_UNKNOWN;
190 webview = (IWebView2WebView*)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME);
191
192 if (webview)
193 webview->ExecuteScript(UTF8toWide(script),
194 Callback<IWebView2ExecuteScriptCompletedHandler>(
195 [hwnd, scriptdata](HRESULT error, PCWSTR result) -> HRESULT
196 {
197 _wndproc(hwnd, WM_USER + 100, (error == S_OK ? (WPARAM)WideToUTF8((LPWSTR)result) : NULL), (LPARAM)scriptdata);
198 return S_OK;
199 }).Get());
200 return DW_ERROR_NONE;
201 } 412 }
202 413
203 /************************** edgeWindowProc() ************************* 414 /************************** edgeWindowProc() *************************
204 * Our message handler for our window to host the browser. 415 * Our message handler for our window to host the browser.
205 */ 416 */
206 417
207 LRESULT CALLBACK _edgeWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 418 LRESULT CALLBACK _edgeWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
208 { 419 {
209 switch (uMsg) 420 if (DW_EDGE)
210 { 421 return DW_EDGE->WndProc(hWnd, uMsg, wParam, lParam);
211 case WM_SIZE: 422 return DefWindowProc(hWnd, uMsg, wParam, lParam);
212 { 423 }
213 // Resize the browser object to fit the window 424 }
214 IWebView2WebView* webview;
215
216 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
217 // we initially attached the browser object to this window.
218 webview = (IWebView2WebView*)dw_window_get_data(hWnd, _DW_HTML_DATA_NAME);
219 // Resize WebView to fit the bounds of the parent window
220 if (webview)
221 {
222 RECT bounds;
223
224 GetClientRect(hWnd, &bounds);
225 webview->put_Bounds(bounds);
226 }
227 return(0);
228 }
229
230 case WM_PAINT:
231 {
232 PAINTSTRUCT ps;
233 HDC hdc = BeginPaint(hWnd, &ps);
234 EndPaint(hWnd, &ps);
235 return(0);
236 }
237
238 case WM_CREATE:
239 {
240 // Step 3 - Create a single WebView within the parent window
241 // Create a WebView, whose parent is the main window hWnd
242 DW_EDGE_ENV->CreateWebView(hWnd, Callback<IWebView2CreateWebViewCompletedHandler>(
243 [hWnd](HRESULT result, IWebView2WebView* webview) -> HRESULT {
244 if (webview != nullptr) {
245 dw_window_set_data(hWnd, _DW_HTML_DATA_NAME, DW_POINTER(webview));
246 }
247
248 // Add a few settings for the webview
249 // this is a redundant demo step as they are the default settings values
250 IWebView2Settings* Settings;
251 webview->get_Settings(&Settings);
252 Settings->put_IsScriptEnabled(TRUE);
253 Settings->put_AreDefaultScriptDialogsEnabled(TRUE);
254 Settings->put_IsWebMessageEnabled(TRUE);
255
256 // Resize WebView to fit the bounds of the parent window
257 RECT bounds;
258 GetClientRect(hWnd, &bounds);
259 webview->put_Bounds(bounds);
260
261 // Save the token, we might need to dw_window_set_data() this value
262 // for later use to remove the handlers
263 EventRegistrationToken token;
264
265 // Register a handler for the NavigationStarting event.
266 webview->add_NavigationStarting(
267 Callback<IWebView2NavigationStartingEventHandler>(
268 [hWnd](IWebView2WebView* sender,
269 IWebView2NavigationStartingEventArgs* args) -> HRESULT
270 {
271 LPWSTR uri;
272 sender->get_Source(&uri);
273
274 _wndproc(hWnd, WM_USER + 101, (WPARAM)DW_INT_TO_POINTER(DW_HTML_CHANGE_STARTED),
275 !wcscmp(uri, L"about:blank") ? (LPARAM)"" : (LPARAM)WideToUTF8((LPWSTR)uri));
276
277 return S_OK;
278 }).Get(), &token);
279
280 // Register a handler for the DocumentStateChanged event.
281 webview->add_DocumentStateChanged(
282 Callback<IWebView2DocumentStateChangedEventHandler>(
283 [hWnd](IWebView2WebView* sender,
284 IWebView2DocumentStateChangedEventArgs* args) -> HRESULT
285 {
286 LPWSTR uri;
287 sender->get_Source(&uri);
288
289 _wndproc(hWnd, WM_USER + 101, (WPARAM)DW_INT_TO_POINTER(DW_HTML_CHANGE_LOADING),
290 !wcscmp(uri, L"about:blank") ? (LPARAM)"" : (LPARAM)WideToUTF8((LPWSTR)uri));
291
292 return S_OK;
293 }).Get(), &token);
294
295 // Register a handler for the NavigationCompleted event.
296 webview->add_NavigationCompleted(
297 Callback<IWebView2NavigationCompletedEventHandler>(
298 [hWnd](IWebView2WebView* sender,
299 IWebView2NavigationCompletedEventArgs* args) -> HRESULT
300 {
301 LPWSTR uri;
302 sender->get_Source(&uri);
303
304 _wndproc(hWnd, WM_USER + 101, (WPARAM)DW_INT_TO_POINTER(DW_HTML_CHANGE_COMPLETE),
305 !wcscmp(uri, L"about:blank") ? (LPARAM)"" : (LPARAM)WideToUTF8((LPWSTR)uri));
306
307 return S_OK;
308 }).Get(), &token);
309
310 // Handle cached load requests due to delayed
311 // loading of the edge webview contexts
312 LPCWSTR url = (LPCWSTR)dw_window_get_data(hWnd, _DW_HTML_DATA_LOCATION);
313 if(url)
314 {
315 webview->Navigate(url);
316 free((void *)url);
317 }
318 LPCWSTR raw = (LPCWSTR)dw_window_get_data(hWnd, _DW_HTML_DATA_RAW);
319 if (raw)
320 {
321 webview->NavigateToString(raw);
322 free((void *)raw);
323 }
324 return S_OK;
325 }).Get());
326 // Success
327 return(0);
328 }
329
330 case WM_DESTROY:
331 {
332 // Detach the browser object from this window, and free resources.
333 IWebView2WebView* webview;
334
335 // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when
336 // we initially attached the browser object to this window.
337 webview = (IWebView2WebView*)dw_window_get_data(hWnd, _DW_HTML_DATA_NAME);
338 if (webview)
339 {
340 dw_window_set_data(hWnd, _DW_HTML_DATA_NAME, NULL);
341 webview->Close();
342 }
343 _free_window_memory(hWnd, 0);
344 return(TRUE);
345 }
346 }
347
348 return(DefWindowProc(hWnd, uMsg, wParam, lParam));
349 }
350 }