原生端和網頁端程序代碼的互操作性
Microsoft Edge WebView2 控制件可讓您將 Web 內容內嵌至原生應用程式。 您可以使用不同的方式使用 WebView2,視您需要完成的工作而定。 本文說明如何使用簡單的訊息、JavaScript 程式代碼和原生對象進行通訊。
一些常見的使用案例包括:
- 流覽至不同的網站之後,更新原生主機視窗標題。
- 從 Web 應用程式傳送原生相機物件並使用其方法。
- 在應用程式的 Web 端執行專用的 JavaScript 檔案。
開始之前
本教學課程會逐步解說範例應用程式程序代碼,以示範 WebView2 中的一些通訊功能。 複製 WebView2Samples 存放庫、在 Visual Studio 中開 .sln
啟檔案、建置專案,然後執行 (偵錯) 以遵循本文中的步驟。
如需複製存放庫的詳細步驟,請參閱 WebView2 範例。
案例:簡單傳訊
WebView2 控制件可讓您在應用程式的 Web 和原生端之間交換簡單的訊息。 您可以使用 或 等JSON
String
數據類型,在主應用程式與 WebView2 之間傳送訊息。
將訊息從主應用程式傳送至 WebView2
此範例顯示範例應用程式如何根據主應用程式的訊息,變更前端文字的色彩。
若要查看傳訊的運作方式:
執行範例應用程式,然後選取 [ 案例 ] 索引標籤,然後選取 [Web 訊息 ] 選項。
下列畫面隨即出現:
請注意標題為
Posting Messages
的第一個區段。 遵循指示,然後選取 [編寫Post Message JSON的腳本>]。 然後按一下 [確定]。 訊息會變成藍色:如何變更文字色彩? 此範例一開始會在原生端建立按鈕。 然後範例會新增下列程序代碼,以在按下按鈕時張貼 Web 訊息。 此程式代碼會將 Web 文字的色彩變更為藍色。
此範例包含C++程序代碼,以建立按兩下時呼叫
SendJsonWebMessage()
的 Windows 按鈕。如需在 C++ 中建立按鈕的詳細資訊,請參閱 如何建立按鈕。
按兩下按鈕時,它會從 ScriptComponent.cpp呼叫下列程式代碼。
// Prompt the user for some JSON and then post it as a web message. void ScriptComponent::SendJsonWebMessage() { TextInputDialog dialog( m_appWindow->GetMainWindow(), L"Post Web Message JSON", L"Web message JSON:", L"Enter the web message as JSON.", L"{\"SetColor\":\"blue\"}"); if (dialog.confirmed) { m_webView->PostWebMessageAsJson(dialog.input.c_str()); } }
注意事項
本教學課程的其餘部分會使用 WebView2 範例中的 檔案
ScenarioWebMessage.html
。 在工作時比較您自己的 HTML 檔案,或複製並貼上 來自ScenarioWebMessage.html的內容。此範例會在 Web 上使用 JavaScript 事件接聽程式。
ScenarioWebMessage.html
標頭中包含下列 JavaScript:window.chrome.webview.addEventListener('message', arg => { if ("SetColor" in arg.data) { document.getElementById("colorable").style.color = arg.data.SetColor; } });
事件接聽程式 會接聽 訊息事件,並讓消息正文具有色彩。
HTML 檔案描述傳訊練習:
<h1>WebMessage sample page</h1> <p>This page demonstrates basic interaction between the host app and the webview by means of Web Messages.</p> <h2>Posting Messages</h2> <p id="colorable">Messages can be posted from the host app to the webview using the functions <code>ICoreWebView2::PostWebMessageAsJson</code> and <code>ICoreWebView2::PostWebMessageAsString</code>. Try selecting the menu item "Script > Post Message JSON" to send the message <code>{"SetColor":"blue"}</code>. It should change the text color of this paragraph.</p>
功能表
Post Message JSON
項位於 Microsoft Visual C++ 產生的資源腳本檔案 WebView2APISample.rc 中。MENUITEM "Post Message JSON", IDM_POST_WEB_MESSAGE_JSON
腳本檔案接著會在ScriptComponent.cpp中呼叫案例
IDM_POST_WEB_MESSAGE_JSON
。case IDM_POST_WEB_MESSAGE_JSON: SendJsonWebMessage(); return true;
這會完成顯示 WebView2 如何透過簡單訊息進行通訊的範例。
透過 postMessage 接收訊息字串
本範例會遵循 Receiving Messages
網頁的 區段,變更標題欄的文字。 主應用程式會收到來自 WebView2 的訊息,其中包含新的標題列文字。
C++檔案會處理標題文字,並以字串形式與主應用程式通訊。
按鍵時,WebView2 會使用
window.chrome.webview.postMessage
中的 ,將訊息從網頁傳輸到原生 應用程式ScenarioWebMessage.html。function SetTitleText() { let titleText = document.getElementById("title-text"); window.chrome.webview.postMessage(`SetTitleText ${titleText.value}`); }
HTML 檔案包含文字框和按鈕,可將訊息傳送至主應用程式:
<h2>Receiving Messages</h2> <p>The host app can receive messages by registering an event handler with <code>ICoreWebView2::add_WebMessageReceived</code>. If you enter text and click "Send", this page will send a message to the host app which will change the text of the title bar.</p> <input type="text" id="title-text"/> <button onclick="SetTitleText()">Send</button>
ScenarioWebMessage.cpp中的事件處理程式 會 處理新的標題文字字串,並以字串形式將它傳達給主應用程式。
// Setup the web message received event handler before navigating to // ensure we don't miss any messages. CHECK_FAILURE(m_webView->add_WebMessageReceived( Microsoft::WRL::Callback<ICoreWebView2WebMessageReceivedEventHandler>( [this](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) { wil::unique_cotaskmem_string uri; CHECK_FAILURE(args->get_Source(&uri)); // Always validate that the origin of the message is what you expect. if (uri.get() != m_sampleUri) { return S_OK; } wil::unique_cotaskmem_string messageRaw; CHECK_FAILURE(args->TryGetWebMessageAsString(&messageRaw)); std::wstring message = messageRaw.get(); if (message.compare(0, 13, L"SetTitleText ") == 0) { m_appWindow->SetTitleText(message.substr(13).c_str()); } else if (message.compare(L"GetWindowBounds") == 0) { RECT bounds = m_appWindow->GetWindowBounds(); std::wstring reply = L"{\"WindowBounds\":\"Left:" + std::to_wstring(bounds.left) + L"\\nTop:" + std::to_wstring(bounds.top) + L"\\nRight:" + std::to_wstring(bounds.right) + L"\\nBottom:" + std::to_wstring(bounds.bottom) + L"\"}"; CHECK_FAILURE(sender->PostWebMessageAsJson(reply.c_str())); } return S_OK; }).Get(), &m_webMessageReceivedToken));
來回訊息
本範例會遵循 <h2>Round trip</h2>
WebMessage 範例頁面的 區段, ScenarioWebMessage.html。 此範例顯示從 WebView2 到主應用程式及返回的來回訊息。 主應用程式會收到來自 WebView2 的要求,並傳回活動視窗的界限。
當主應用程式要求時,C++檔案會取得視窗界限,並以 JSON Web 訊息的形式將數據傳送至 WebView2。
HTML 檔案包含一個按鈕,可從主應用程式取得視窗範圍:
<h2>Round trip</h2> <p>The host app can send messages back in response to received messages. If you click the <b>Get window bounds</b> button, the host app reports back the bounds of its window, which are displayed in the text box.</p> <button onclick="GetWindowBounds()">Get window bounds</button><br> <textarea id="window-bounds" rows="4" readonly></textarea>
當使用者按鍵時,WebView2 會使用
window.chrome.webview.postMessage
將訊息從網頁傳輸到原生應用程式。function GetWindowBounds() { window.chrome.webview.postMessage("GetWindowBounds"); }
ScenarioWebMessage.cpp中的事件處理程式會取得視窗界限,並使用
TryGetWebMessageAsString
將數據傳送至主應用程式:// Setup the web message received event handler before navigating to // ensure we don't miss any messages. CHECK_FAILURE(m_webView->add_WebMessageReceived( Microsoft::WRL::Callback<ICoreWebView2WebMessageReceivedEventHandler>( [this](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) { wil::unique_cotaskmem_string uri; CHECK_FAILURE(args->get_Source(&uri)); // Always validate that the origin of the message is what you expect. if (uri.get() != m_sampleUri) { return S_OK; } wil::unique_cotaskmem_string messageRaw; CHECK_FAILURE(args->TryGetWebMessageAsString(&messageRaw)); std::wstring message = messageRaw.get(); if (message.compare(0, 13, L"SetTitleText ") == 0) { m_appWindow->SetTitleText(message.substr(13).c_str()); } else if (message.compare(L"GetWindowBounds") == 0) { RECT bounds = m_appWindow->GetWindowBounds(); std::wstring reply = L"{\"WindowBounds\":\"Left:" + std::to_wstring(bounds.left) + L"\\nTop:" + std::to_wstring(bounds.top) + L"\\nRight:" + std::to_wstring(bounds.right) + L"\\nBottom:" + std::to_wstring(bounds.bottom) + L"\"}"; CHECK_FAILURE(sender->PostWebMessageAsJson(reply.c_str())); } return S_OK; }).Get(), &m_webMessageReceivedToken));
視窗界限會顯示在網頁上。
案例:傳送 JavaScript 程式代碼
此案例示範如何在 Web 端執行 JavaScript。 在此方法中,主應用程式會指定要執行的 JavaScript 程式代碼,並透過 ExecuteScriptAsync
將程式代碼傳遞至 Web。 函 ExecuteScriptAsync
式會將 JavaScript 結果傳回給 ExecuteScript
呼叫端。
如需詳細資訊,請 參閱在 WebView2 中使用 JavaScript (從原生程式代碼執行 JavaScript) 。
案例:傳送原生物件
將原生對象傳遞至 Web。 然後從 Web 呼叫物件的方法。
若要使用代表方法呼叫的訊息,請使用 AddHostObjectToScript
API。 概括而言,此 API 可讓您將原生 (主機) 對象公開到 Web 端,並作為 Proxy。 使用 window.chrome.webview.hostObjects.{name}
來存取這些物件。
在介面 ICoreWebView2 的 AddHostObjectToScript 區段中會說明將原生對象傳遞至應用程式的 Web 端。
恭喜您! 您已成功將 Web 內容內嵌至原生應用程式。
另請參閱
- WebView2 功能和 API 概觀中的 Web/原生 Interop。