Mercurial > dwindows
diff win/edge.cpp @ 1999:4e808c4cadfb
Win: Add initial support for Microsoft Edge (Chromium) embedding.
Only works with Visual Studio currently due to the SDK being a nuget package.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Thu, 31 Oct 2019 07:01:35 +0000 |
parents | |
children | 77e43d71eaa7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/win/edge.cpp Thu Oct 31 07:01:35 2019 +0000 @@ -0,0 +1,245 @@ +/* edge.cpp + * + * Allows dw_html_new() to embed a Microsoft Edge (Chromium) browser. + * + * Requires Windows 10, 8 or 7 with Microsoft Edge (Chromium) installed. + * + * Only included when BUILD_EDGE is defined, will fall back to embedded IE. + * + * Currently only buildable with Visual Studio since it requires the EDGE + * SDK which is currently distributed as a nuget package. + */ +#include "dw.h" +#include "webview2.h" + +#define _DW_HTML_DATA_NAME (char *)"_dw_edge" + +BOOL _dw_edge_detect(VOID) +{ + return TRUE; +} + +/******************************* dw_html_action() ************************** + * Implements the functionality of a "Back". "Forward", "Home", "Search", + * "Refresh", or "Stop" button. + * + * hwnd = Handle to the window hosting the browser object. + * action = One of the following: + * 0 = Move back to the previously viewed web page. + * 1 = Move forward to the previously viewed web page. + * 2 = Move to the home page. + * 3 = Search. + * 4 = Refresh the page. + * 5 = Stop the currently loading page. + * + * NOTE: EmbedBrowserObject() must have been successfully called once with the + * specified window, prior to calling this function. You need call + * EmbedBrowserObject() once only, and then you can make multiple calls to + * this function to display numerous pages in the specified window. + */ + +void _dw_edge_action(HWND hwnd, int action) +{ + IWebView2WebView* webview; + + // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when + // we initially attached the browser object to this window. + + webview = *((IWebView2WebView**)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME)); + // We want to get the base address (ie, a pointer) to the IWebBrowser2 object embedded within the browser + // object, so we can call some of the functions in the former's table. + if (webview) + { + // Ok, now the pointer to our IWebBrowser2 object is in 'webBrowser2', and so its VTable is + // webBrowser2->lpVtbl. + + // Call the desired function + switch (action) + { + case DW_HTML_GOBACK: + { + // Call the IWebBrowser2 object's GoBack function. + webview->GoBack(); + break; + } + + case DW_HTML_GOFORWARD: + { + // Call the IWebBrowser2 object's GoForward function. + webview->GoForward(); + break; + } + + case DW_HTML_GOHOME: + { + // Call the IWebBrowser2 object's GoHome function. + //webview->GoHome(); + break; + } + + case DW_HTML_SEARCH: + { + // Call the IWebBrowser2 object's GoSearch function. + //webview->GoSearch(); + break; + } + + case DW_HTML_RELOAD: + { + // Call the IWebBrowser2 object's Refresh function. + webview->Reload(); + } + + case DW_HTML_STOP: + { + // Call the IWebBrowser2 object's Stop function. + //webview->Stop(); + } + } + } +} + +/******************************* dw_html_raw() **************************** + * Takes a string containing some HTML BODY, and displays it in the specified + * window. For example, perhaps you want to display the HTML text of... + * + * <P>This is a picture.<P><IMG src="mypic.jpg"> + * + * hwnd = Handle to the window hosting the browser object. + * string = Pointer to nul-terminated string containing the HTML BODY. + * (NOTE: No <BODY></BODY> tags are required in the string). + * + * RETURNS: 0 if success, or non-zero if an error. + * + * NOTE: EmbedBrowserObject() must have been successfully called once with the + * specified window, prior to calling this function. You need call + * EmbedBrowserObject() once only, and then you can make multiple calls to + * this function to display numerous pages in the specified window. + */ + +int _dw_edge_raw(HWND hwnd, LPCWSTR string) +{ + IWebView2WebView* webview; + + // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when + // we initially attached the browser object to this window. + webview = *((IWebView2WebView**)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME)); + + if (webview) + { + return DW_ERROR_NONE; + } + return DW_ERROR_UNKNOWN; +} + +/******************************* dw_html_url() **************************** + * Displays a URL, or HTML file on disk. + * + * hwnd = Handle to the window hosting the browser object. + * webPageName = Pointer to nul-terminated name of the URL/file. + * + * RETURNS: 0 if success, or non-zero if an error. + * + * NOTE: EmbedBrowserObject() must have been successfully called once with the + * specified window, prior to calling this function. You need call + * EmbedBrowserObject() once only, and then you can make multiple calls to + * this function to display numerous pages in the specified window. + */ + +int _dw_edge_url(HWND hwnd, LPCWSTR url) +{ + IWebView2WebView * webview; + + // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when + // we initially attached the browser object to this window. + webview = *((IWebView2WebView**)dw_window_get_data(hwnd, _DW_HTML_DATA_NAME)); + + if (webview) + { + webview->Navigate(url); + return DW_ERROR_NONE; + } + return DW_ERROR_UNKNOWN; +} + +/************************** browserWindowProc() ************************* + * Our message handler for our window to host the browser. + */ + +LRESULT CALLBACK _edgeWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_SIZE: + { + // Resize the browser object to fit the window + RECT bounds; + IWebView2WebView* webview; + + // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when + // we initially attached the browser object to this window. + webview = *((IWebView2WebView**)dw_window_get_data(hWnd, _DW_HTML_DATA_NAME)); + GetClientRect(hWnd, &bounds); + // Resize WebView to fit the bounds of the parent window + if(webview) + webview->put_Bounds(bounds); + return(0); + } + + case WM_CREATE: + { + // Step 3 - Create a single WebView within the parent window + // Locate the browser and set up the environment for WebView + CreateWebView2EnvironmentWithDetails(nullptr, nullptr, nullptr, + Callback<IWebView2CreateWebView2EnvironmentCompletedHandler>( + [hWnd](HRESULT result, IWebView2Environment* env) -> HRESULT { + + // Create a WebView, whose parent is the main window hWnd + env->CreateWebView(hWnd, Callback<IWebView2CreateWebViewCompletedHandler>( + [hWnd](HRESULT result, IWebView2WebView* webview) -> HRESULT { + if (webview != nullptr) { + dw_window_set_data(hWnd, _DW_HTML_DATA_NAME, DW_POINTER(webview)); + } + + // Add a few settings for the webview + // this is a redundant demo step as they are the default settings values + IWebView2Settings* Settings; + webview->get_Settings(&Settings); + Settings->put_IsScriptEnabled(TRUE); + Settings->put_AreDefaultScriptDialogsEnabled(TRUE); + Settings->put_IsWebMessageEnabled(TRUE); + + // Resize WebView to fit the bounds of the parent window + RECT bounds; + GetClientRect(hWnd, &bounds); + webview->put_Bounds(bounds); + return S_OK; + }).Get()); + return S_OK; + }).Get()); + + // Success + return(0); + } + + case WM_DESTROY: + { + // Detach the browser object from this window, and free resources. + IWebView2WebView* webview; + + // Retrieve the browser object's pointer we stored in our window's GWL_USERDATA when + // we initially attached the browser object to this window. + webview = *((IWebView2WebView**)dw_window_get_data(hWnd, _DW_HTML_DATA_NAME)); + if (webview) + { + dw_window_set_data(hWnd, _DW_HTML_DATA_NAME, NULL); + webview->Close(); + + } + return(TRUE); + } + } + + return(DefWindowProc(hWnd, uMsg, wParam, lParam)); +} +