原生端和網頁端程式碼的互通性

Microsoft Edge WebView2 控制項可讓您將 Web 內容內嵌至原生應用程式。 您可以使用不同的方式使用 WebView2,視您需要完成的工作而定。 本文說明如何使用簡單的訊息、JavaScript 程式碼和原生物件進行通訊。

一些常見的使用案例包括:

  • 流覽至不同的網站之後,更新原生主機視窗標題。
  • 從 Web 應用程式傳送原生相機物件並使用其方法。
  • 在應用程式的 Web 端執行專用的 JavaScript 檔案。

開始之前

本教學課程會逐步解說範例應用程式程式碼,以示範 WebView2 中的一些通訊功能。 複製 WebView2Samples 存放庫、在 Visual Studio 中開 .sln 啟檔案、建置專案,然後執行 (偵錯) 以遵循本文中的步驟。

如需複製存放庫的詳細步驟,請參閱 WebView2 範例

案例:簡單傳訊

WebView2 控制項可讓您在應用程式的 Web 和原生端之間交換簡單的訊息。 您可以使用 或 等 JSONString 資料類型,在主應用程式與 WebView2 之間傳送訊息。

將訊息從主應用程式傳送至 WebView2

此範例顯示範例應用程式如何根據主應用程式的訊息,變更前端文字的色彩。

若要查看傳訊的運作方式:

  1. 執行範例應用程式,然後選取 [ 案例 ] 索引標籤,然後選取 [Web 訊息 ] 選項。

    下列畫面隨即出現:

    Web 訊息範例頁面,示範主應用程式與 WebView2 實例之間使用 Web 訊息的基本互動

  2. 請注意標題為 Posting Messages 的第一個區段。 遵循指示,然後選取 [編寫Post Message JSON的腳本> ]。 然後按一下 [確定]。 訊息會變成藍色:

    「張貼 Web 訊息 JSON」示範

    如何變更文字色彩? 此範例一開始會在原生端建立按鈕。 然後範例會新增下列程式碼,以在按一下按鈕時張貼 Web 訊息。 此程式碼會將 Web 文字的色彩變更為藍色。

    此範例包含 C++ 程式碼,可建立按一下時呼叫 SendJsonWebMessage() 的 Windows 按鈕。

    如需使用 C++ 建立按鈕的詳細資訊,請參閱 如何建立按鈕

  3. 按一下按鈕時,它會從 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 事件接聽程式。

  4. ScenarioWebMessage.html 標頭中包含下列 JavaScript:

    window.chrome.webview.addEventListener('message', arg => {
       if ("SetColor" in arg.data) {
          document.getElementById("colorable").style.color = 
          arg.data.SetColor;
       }
    });
    

    事件接聽程式 會接聽 訊息事件,並讓郵件內文具有色彩。

  5. 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>
    
  6. 功能表 Post Message JSON 項位於Microsoft Visual C++產生的資源腳本檔案WebView2APISample.rc中。

    MENUITEM "Post Message JSON",           IDM_POST_WEB_MESSAGE_JSON
    
  7. 腳本檔案接著會在ScriptComponent.cpp中呼叫案例 IDM_POST_WEB_MESSAGE_JSON

    case IDM_POST_WEB_MESSAGE_JSON:
       SendJsonWebMessage();
       return true;
    

這會完成顯示 WebView2 如何透過簡單訊息進行通訊的範例。

透過 postMessage 接收訊息字串

本範例會遵循 Receiving Messages 網頁的 區段,變更標題列的文字。 主應用程式會收到來自 WebView2 的訊息,其中包含新的標題列文字。

C++ 檔案會處理標題文字,並以字串形式與主應用程式通訊。

  1. 按一下按鈕時,WebView2 會使用 window.chrome.webview.postMessage 中的 ,將訊息從網頁傳輸到原生 應用程式ScenarioWebMessage.html

    function SetTitleText() {
       let titleText = document.getElementById("title-text");
       window.chrome.webview.postMessage(`SetTitleText ${titleText.value}`);
    }
    
  2. 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>
    
  3. 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。

  1. 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>
    
  2. 當使用者按一下按鈕時,WebView2 會使用 window.chrome.webview.postMessage 將訊息從網頁傳輸到原生應用程式。

    function GetWindowBounds() {
       window.chrome.webview.postMessage("GetWindowBounds");
    }
    
  3. 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} 來存取這些物件。

介面 ICoreWebView2AddHostObjectToScript區段中會說明將原生物件傳遞至應用程式的 Web 端。

恭喜您! 您已成功將 Web 內容內嵌至原生應用程式。

另請參閱