Win32 範例應用程式

WebView2APISample 應用程式示範如何使用 WebView2 控制項和 WebView2 API,將功能新增至 Win32 C++應用程式。

  • 範例名稱: WebView2APISample
  • 存放庫目錄: WebView2APISample
  • 方案檔: WebView2Samples.sln 位於父目錄中的 (, \SampleApps\)
  • 方案總管中的項目名稱: WebView2APISample

WebView2APISample 會在 Win32 原生應用程式內嵌 WebView2 控制件。

此範例是建置為 Win32 Visual Studio 2019 專案。 它會在 WebView2 環境中使用 C++ 和 HTML/CSS/JavaScript。

WebView2APISample 展示 WebView2 事件處理程式和 API 方法的選取專案,可讓原生 Win32 應用程式直接與 WebView2 控件互動,反之亦然。

此範例及其方案檔是唯一的:它包含 [方案總管] 中其他範例的複本。

WebView2APISample 是使用 Microsoft Edge WebView2 控制件所建置的混合式應用程式;也就是說,此應用程式結合了原生端和瀏覽器 Web 應用程式端。 請參閱 Microsoft Edge WebView2 簡介中的混合式應用程式方法

執行中的 WebView2APISample 應用程式視窗會顯示 WebView2 SDK 版本,以及 WebView2 運行時間版本和路徑。 為您提供許多實用的功能表和功能表:

顯示 WebView2 SDK 版本和 WebView2 執行時間版本和路徑的 WebView2APISample 應用程式視窗

如果這是您第一次使用 WebView,建議您先遵循 在 Win32 應用程式中開始使用 WebView2 教學課程,該教學課程將逐步說明如何建立 WebView2 應用程式,並逐步解說一些基本的 WebView2 功能。 該特定教學課程不會從您使用專案範本建立新的 Win32 項目開始;相反地,它會從 WebView2Samples 存放庫中的已完成項目開始,並逐步引導您完成新增的 WebView2 程式代碼。

如需 WebView2 中事件和 API 處理程式的詳細數據,請參閱 WebView2 API 參考

步驟 1 - 安裝 Visual Studio

Microsoft Visual Studio 必須 (最低版本:Visual Studio 2019) 。 Microsoft此範例不支援 Visual Studio Code。 此存放庫範例是Visual Studio 2019專案。 此範例也可以使用 Visual Studio 2022 開啟。

  1. 如果 Visual Studio 尚未與C++支援一起安裝,請在個別的視窗或索引標籤中,參閱在設定 WebView2 的開發環境安裝 Visual Studio。 請依照該節中的步驟安裝具有C++支援的Visual Studio,然後返回此頁面並繼續執行下列步驟。

如果您想要使用 Visual Studio 2017,請在 Visual Studio 2017 中開啟方案之後,變更專案屬性組態屬性>一般>平臺工具組中的專案>平臺工具組

若要使用 Visual Studio 2017,您可能也需要在電腦上安裝最新的 Windows SDK。

步驟 2 - 複製 WebView2Samples 存放庫

  1. 如果尚未完成,請將存放庫複製 WebView2Sample 到本機磁碟驅動器。 在個別的視窗或索引標籤中,請參閱為 WebView2 設定開發環境中的下載 WebView2Samples 存放庫。 請遵循該區段中的步驟,然後返回此頁面,然後繼續進行下列步驟。

  2. 如果您先前已複製存放庫,請將最新的認可提取到存放庫的本地副本。

步驟 3 - 在 Visual Studio 中開啟解決方案

  1. 在本機磁碟驅動器上,在 Visual Studio 中開 .sln 啟 檔案:

    • <your-repos-directory>/WebView2Samples/SampleApps/WebView2Samples.sln

    或:

    • <your-repos-directory>/WebView2Samples-main/SampleApps/WebView2Samples.sln

WebView2APISample 範例和專案是主要 Win32 範例。

不同於其他範例,範例存放庫目錄中沒有包含此範例自述檔的專用 .sln 檔案。 相反地 .sln ,此範例的檔案 (包含其他範例專案以及) 位於父目錄中。

方案總管中方案中的所有專案

步驟 4 - 出現提示時安裝工作負載

  1. Visual Studio 工作負載 - 如果出現提示,請安裝任何要求的 Visual Studio 工作負載。 在個別的視窗或索引標籤中,請參閱為 WebView2 設定開發環境中的安裝 Visual Studio 工作負載。 請遵循該區段中的步驟,然後返回此頁面,然後繼續進行下列步驟。

繼續執行下列步驟。

步驟 5 - 檢視已開啟的專案

  1. 在本機磁碟驅動器上,在您設定的相同 Visual Studio 版本中再次開啟 WebView2Samples 解決方案:

    • <your-repos-directory>/WebView2Samples/SampleApps/WebView2Samples.sln

    或:

    • <your-repos-directory>/WebView2Samples-main/SampleApps/WebView2Samples.sln
  2. 按兩下 [ 確定] 按鈕。 [ 複位目標專案] 對話框可能會開啟:

    [複位目標專案] 對話框

    已安裝版本的範例:

    複位目標 - 已安裝 SDK

  3. 按兩下 [ 確定] 按鈕。

方案總管會顯示數個專案,包括 WebView2APISample 專案:

方案總管中的 WebView2APISample 專案

步驟 6 - 使用已安裝的 SDK 版本建置專案

在 Visual Studio 頂端設定建置目標,如下所示:

  1. 在 [ 方案組態] 下拉式清單中,選取 [ 偵錯] 或 [ 發行]

  2. 在 [ 解決方案平臺] 下拉式清單中,選取 [x86]、 [x64] 或 [ARM64]

  3. [方案總管] 中,以滑鼠右鍵按兩下 WebView2APISample 專案,然後選取 [ 建置]

    在方案總管中選取的 WebView2APISample 專案

    這會建置項目檔 SampleApps/WebView2APISample/WebView2APISample.vcxproj

步驟 7 - 在專案) 執行 (偵錯

  1. 取 [偵錯>開始偵 錯] (F5) 。

    疑難解答:如果您略過建置步驟,並立即選>取 [偵錯開始偵錯 (F5) ,可能會出現對話框「無法啟動程式:找不到指定的路徑」:

    對話框:無法啟動程式:找不到指定的路徑

    若要修正此問題:在 [ 方案總管] 中,以滑鼠右鍵按兩下 WebView2APISample 專案,然後選取 [ 建置]

    WebView2APISample 應用程式視窗隨即開啟:

    WebView2APISample 應用程式視窗

  2. 在 Visual Studio 中,選取 [ 偵錯>停止偵錯]。 Visual Studio 會關閉應用程式。

步驟 8 - 更新發行前版本 WebView2 SDK

接下來,您將更新 WebView2 SDK,然後重新建置專案。

如果您想要在 GitHub 的 WebView2APISample 應用程式的存放庫複本中快速查看已安裝的 WebView2 SDK 版本,請 參閱packages.config

此範例的存放庫版本已安裝 WebView2 SDK 發行前版本。 在下方,您會將它更新為 WebView2 SDK 的最新發行前版本,或確認已安裝最新的 SDK。 使用發行前版本 SDK 可讓您存取最新的功能。

檢查並可能更新已安裝的 NuGet 套件,如下所示:

  1. 在 [方案總管] 中,以滑鼠右鍵按兩下 WebView2APISample 專案, (不是其上方的方案節點) ,然後選取 [ 管理 NuGet 套件]

    [NuGet 套件管理員] 面板會在 Visual Studio 中開啟。

  2. 在搜尋文字框右側,選取 [ 包含發行前版本] 複 選框。

  3. NuGet 套件管理員中,按兩下 [ 已安裝] 索引標籤 。在每個套件的右側,檢查是否列出較新的版本號碼以及現有的版本號碼。

  4. 按兩下 [ 更新] 索引 標籤。如果 WebView2 或 WIL 套件有可用的更新,您可以在這裡更新套件。

  5. 如果您想要能夠嘗試最新的 API,請在右側的 [ 版本 ] 下拉式清單中,確定已選取 [最新發行前版本 ]:

    已選取 WebView2 SDK 發行前版本的 NuGet 套件管理員

  6. 按兩下 [ 更新] 按鈕。

    [ 預覽變更] 對話框隨即出現:

    WebView2 NugGet 套件的 [預覽變更] 對話方塊

    上述影像來自另一個專案,但很類似。

  7. 按兩下 [ 確定] 按鈕。

此專案現在已安裝最新版的 WebView2 SDK。

步驟 9 - 使用更新的 SDK 建置和執行專案

  1. [方案總管] 中,以滑鼠右鍵按兩下 WebView2APISample 專案,然後選取 [ 建置]

    在方案總管中選取的 WebView2APISample 專案

  2. 取 [偵錯>開始偵 錯] (F5) 。

    WebView2APISample 應用程式視窗隨即開啟:

    WebView2APISample 應用程式視窗

  3. 使用 WebView2APISample 應用程式。

  4. 在 Visual Studio 中,選取 [ 偵錯>停止偵錯]。 Visual Studio 會關閉應用程式。

這會完成建置和執行 Win32 範例應用程式的編號步驟。 接下來,在Visual Studio程式碼編輯器中,根據下列各節檢查程序代碼。

混合式應用程式架構

WebView2APISample 應用程式是混合式應用程式的範例,其中包含 Win32 原生元件和 WebView 元件。

  • Win32 元件可以直接存取原生 Windows API。
  • WebView 是標準 Web 技術的容器, (HTML、CSS 和 JavaScript) 。

混合式應用程式

  • 第 1 節: WebView2APISample 應用程式的最上層部分是以 C++ 撰寫的 Win32 元件。 應用程式的這個部分會接受使用者的 UI 輸入,並使用它們來控制 WebView。

  • 第 2 節: WebView2APISample 應用程式的主要部分是 WebView,可使用 HTML/CSS/JavaScript) (的標準 Web 技術來重新規劃。 您可以瀏覽至網站或本機內容。

此混合式方法可讓您使用 Web 技術更快速地建立和逐一查看,同時仍可利用原生功能。 WebView2APISample 應用程式示範 Win32 元件和 WebView 元件如何彼此互動。

這個範圍廣泛的範例應用程式已成長為包含超過150個功能表項,在Win32/C++ 架構中示範許多WebView2 API。 下列各節著重於混合式應用程式實作的基本概念。

項目檔

本節簡短說明存放庫內的一些密鑰檔。 WebView2APISample 應用程式會垂直分割成元件,而不是水準分成圖層。 每個元件都會實作範例功能類別的整個工作流程,從接聽功能表命令,到呼叫WebView API方法來實作它們。

App.cpp

這是執行 WebView2APISample 應用程式的最上層檔案。 它會讀取命令行選項、設定進程環境,以及處理應用程式的線程模型。

AppWindow.cpp (窗口菜单)

此檔案會執行下列動作來實作應用程式視窗:

  1. 設定所有 Win32 控制件。

  2. 初始化 WebView 環境和 WebView。

  3. 將事件處理程式新增至 WebView,並建立處理應用程式各種功能的所有元件。

類別 AppWindow 會從範例應用程式的 [ 視窗 ] 功能表處理命令。

此檔案會在AppWindow.cpp 中的重要函式中詳細說明,如下所示。

FileComponent.cpp (档案] 功能表)

此元件會處理 [檔案] 功能表 (的命令,DocumentTitleChanged[結束) ] 和 事件除外。

ScriptComponent.cpp (脚本菜单)

此元件會從 [腳本 ] 功能表處理命令,其中包含插入JavaScript、張貼WebMessage、將原生物件新增至網頁,或使用DevTools通訊協定與網頁通訊通訊,以與WebView互動。

ProcessComponent.cpp (处理] 功能表)

此元件會處理 [ 處理 ] 功能表中的命令,其中包含與瀏覽器進程的互動。 它也會處理 ProcessFailed 事件,以防瀏覽器進程或其其中一個轉譯進程損毀或沒有回應。

SettingsComponent.cpp (设定] 功能表)

此元件會處理 [設定] 選單 中的 命令。 建立新的 WebView 時,此元件也會負責從舊的 WebView 複製設定。 大部分與介面互動的 ICoreWebView2Settings 程式代碼都會在這裡找到。

ViewComponent.cpp (检视菜单)

此元件會處理來自 [ 檢視 ] 功能表的命令,以及與調整WebView大小和可見度相關的任何功能。 當應用程式視窗重設大小、最小化或還原時, ViewComponent 將會重設大小、隱藏或顯示 WebView 以回應。 它也會回應 ZoomFactorChanged 事件。

ScenarioWebMessage.cpp和 ScenarioWebMessage.html (案例] 功能表)

當您選取 [ScenarioWebMessage案例Web 訊息] 功能表項時,>就會建立元件。 此元件會實作範例應用程式,其中包含C++元件和 HTML + JavaScript 元件,可透過異步張貼和接收訊息來彼此通訊。

此元件會在以下的 ScenarioWebMessage (.html、.cpp 和 .h) 中詳細說明。

ScenarioAddHostObject.cpp和 ScenarioAddHostObject.html (案例] 功能表)

當您選取 [案例主機物件] 功能表項時,>就會建立此元件。 它示範透過主機物件插入,在原生應用程式與 HTML 網頁之間進行通訊。 主物件的介面會在 中 HostObjectSample.idl宣告,而 物件本身會在 中實作 HostObjectSampleImpl.cpp

另請參閱:

AppWindow.cpp中的關鍵函式

AppWindow.cpp 執行下列動作來實作應用程式視窗:

  1. 設定所有 Win32 控制件。

  2. 初始化 WebView 環境和 WebView。

  3. 將事件處理程式新增至 WebView,並建立處理應用程式各種功能的所有元件。

類別 AppWindow 會從範例應用程式的 [ 視窗 ] 功能表處理命令。 以下是 中的一些主要函式 AppWindow.cpp

InitializeWebView ()

AppWindow.cpp中,函 InitializeWebView() 式會使用 CreateCoreWebView2EnvironmentWithOptions 建立 WebView2 環境。

若要查看這些 API 呼叫的運作方式,請從 InitializeWebView()檢查下列程式代碼:

HRESULT hr = CreateCoreWebView2EnvironmentWithOptions(
    subFolder, nullptr, options.Get(),
    Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
        this, &AppWindow::OnCreateEnvironmentCompleted)
        .Get());
if (!SUCCEEDED(hr))
{
    if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
    {
        MessageBox(
            m_mainWindow,
            L"Couldn't find Edge installation. "
            "Do you have a version installed that's compatible with this "
            "WebView2 SDK version?",
            nullptr, MB_OK);
    }
    else
    {
        ShowFailure(hr, L"Failed to create webview environment");
    }
}

OnCreateEnvironmentCompleted ()

建立環境之後,我們會使用 CreateCoreWebView2Controller來建立 WebView。

OnCreateEnvironmentCompleted 調函式會在 中傳遞至 CreateCoreWebView2EnvironmentWithOptionsInitializeWebView()。 回呼會儲存環境指標,然後使用它來建立新的 WebView:

HRESULT AppWindow::OnCreateEnvironmentCompleted(
    HRESULT result, ICoreWebView2Environment* environment)
{
    CHECK_FAILURE(result);

    m_webViewEnvironment = environment;

    CHECK_FAILURE(m_webViewEnvironment->CreateCoreWebView2Controller(
        m_mainWindow, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
                            this, &AppWindow::OnCreateCoreWebView2ControllerCompleted)
                            .Get()));
    return S_OK;
}

OnCreateCoreWebView2ControllerCompleted ()

OnCreateCoreWebView2ControllerCompleted 調函式會在 中傳遞至 CreateCoreWebView2ControllerInitializeWebView()。 此回呼:

  • 初始化 WebView 相關的狀態。
  • 註冊一些事件處理程式。
  • 建立應用程式元件。

RegisterEventHandlers ()

RegisterEventHandlers 式會在內 CreateCoreWebView2Controller呼叫。 它會設定應用程式所使用的一些事件處理程式,並將其新增至 WebView。

如需 WebView2 中事件處理程式的詳細資訊,請參閱 ICoreWebView2

以下是 來自 RegisterEventHandlers()的代碼段,我們會在其中設定 事件的事件處理程式 NewWindowRequested 。 當網頁中的 JavaScript 呼叫 window.open()時,就會引發此事件。 ICoreWebView2NewWindowRequestedEventHandler會建立新的 AppWindow ,並將新視窗的 WebView 傳回瀏覽器,以便從呼叫傳window.open()回它。 不同於對 和 CreateCoreWebView2Controller的呼叫CreateCoreWebView2EnvironmentWithOptions,我們只會提供C++ Lambda,而不是提供回呼的方法:

CHECK_FAILURE(m_webView->add_NewWindowRequested(
    Callback<ICoreWebView2NewWindowRequestedEventHandler>(
        [this](
            ICoreWebView2* sender,
            ICoreWebView2NewWindowRequestedEventArgs* args) {
            wil::com_ptr<ICoreWebView2Deferral> deferral;
            CHECK_FAILURE(args->GetDeferral(&deferral));

            auto newAppWindow = new AppWindow(L"");
            newAppWindow->m_isPopupWindow = true;
            newAppWindow->m_onWebViewFirstInitialized = [args, deferral, newAppWindow]() {
                CHECK_FAILURE(args->put_NewWindow(newAppWindow->m_webView.get()));
                CHECK_FAILURE(args->put_Handled(TRUE));
                CHECK_FAILURE(deferral->Complete());
            };

            return S_OK;
        })
        .Get(),
    nullptr));

ScenarioWebMessage (.html、.cpp 和 .h)

這些 ScenarioWebMessage 檔案顯示 Win32 主機如何修改 WebView、WebView 如何修改 Win32 主機,以及 WebView 如何透過從 Win32 主機存取資訊來修改本身。 這是以異步方式完成。

當您選取 [ScenarioWebMessage案例Web 訊息] 功能表項時,>就會建立元件。 元件會 ScenarioWebMessage 實作具有C++元件和 HTML+JavaScript 元件的範例應用程式,其會透過異步張貼和接收訊息來彼此通訊:

Web 訊息:張貼和接收訊息

下列各節示範每個離散函式如何使用 WebView2APISample 應用程式運作,然後說明如何實作這項功能。

首先,移至範例應用程式內 的 ScenarioWebMessage Web 應用程式:

  1. 開啟 () WebView2APISample 應用程式執行。

  2. 在 [ 案例] 功能表中,選取 [ Web 訊息]

    WebView 會顯示標題為 WebMessage 範例頁面的 網頁 (ScenarioWebMessage.html) :

    用於張貼和接收訊息的 Web 訊息

若要探索 ScenarioWebMessage 功能,您可以遵循頁面上的指示,或遵循下列步驟。

將訊息從 Win32 主機張貼到 WebView

下列步驟顯示 Win32 主機如何修改 WebView。 在此範例中,您會將文字變成藍色:

  1. 開啟 WebMessage 範例頁面 (ScenarioWebMessage.html) ,如上所述。

  2. 在 [ 腳本] 功能表中,選取 [張貼 Web 訊息 JSON]

    包含預先撰寫程式代碼 {"SetColor":"blue"} 的對話框隨即出現。

  3. 按一下確定

    頁面 [ 張貼訊息 ] 區段中的文字會從黑色變更為藍色。

運作方式
  1. ScriptComponent.cpp中,對 PostWebMessageAsJson 的 呼叫會將使用者輸入張貼到 ScenarioMessage.html Web 應用程式:

    // 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());
       }
    }
    
  2. 在 Web 應用程式中,會使用事件接聽程式來接收和回應 Web 訊息。 下列代碼段來自 ScenarioWebMessage.html。 如果自變數為 「SetColor」,事件接聽程式會變更文字的色彩:

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

接收從 WebView 到 Win32 主機 (訊息)

下列步驟示範 WebView 如何藉由變更 Win32 應用程式的標題來修改 Win32 主機應用程式:

  1. 開啟 WebMessage 範例頁面 (ScenarioWebMessage.html) ,如上所述。

  2. 請注意 WebView2APISample 應用程式的標題,該應用程式會顯示在圖示旁邊的視窗左上方。 一開始是 WebView2APISample - Microsoft Edge WebView2

  3. 在頁面的 [ 接收訊息 ] 區段中,輸入新的標題,然後按兩下 [ 傳送] 按鈕。

  4. 請注意 WebView2APISample 應用程式標題列中顯示的新標題。

運作方式
  1. ScenarioWebMessage.html中, window.chrome.webview.postMessage () 會將使用者輸入傳送至主應用程式:

    function SetTitleText() {
       let titleText = document.getElementById("title-text");
       window.chrome.webview.postMessage(`SetTitleText ${titleText.value}`);
    }
    
  2. 在 中 ScenarioWebMessage.cpp,我們會使用 add_WebMessageReceived 來註冊事件處理程式。 當我們收到事件時,在驗證輸入之後,我們會變更應用程式視窗的標題 () m_appWindow

    // 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());
       }
       return S_OK;
    }).Get(), &m_webMessageReceivedToken));
    

往返訊息 (從 WebView 到主機回到 WebView)

下列步驟示範 WebView 如何從 Win32 主機取得資訊,並藉由顯示 Win32 應用程式的大小來修改本身。

  1. 開啟 WebMessage 範例頁面 (ScenarioWebMessage.html) ,如上所述。

  2. 在頁面的 [ 來回行程 ] 區段中,按兩下 [GetWindowBounds] 按鈕。

    按鈕下方的文字框會顯示 WebView2APISample 應用程式的界限。

運作方式
  1. 按兩下 [取得視窗範圍] 按鈕時,會呼叫 中的GetWindowBoundsScenarioWebMessage.html函式。 GetWindowBounds 呼叫 window.chrome.webview.postMessage () 將訊息傳送至主應用程式:

    function GetWindowBounds() {
        window.chrome.webview.postMessage("GetWindowBounds");
    }
    
  2. ScenarioWebMessage.cpp中,我們會使用 add_WebMessageReceived 來註冊接收的事件處理程式。 驗證輸入之後,事件處理程式會從應用程式視窗取得視窗界限。 PostWebMessageAsJson 會將界限傳送至 Web 應用程式:

    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()));
    }
    
  3. ScenarioWebMessage.html中,事件接聽程式會回應 WindowBounds 訊息,並顯示視窗的界限:

    window.chrome.webview.addEventListener('message', arg => {
       if ("WindowBounds" in arg.data) {
          document.getElementById("window-bounds").value = arg.data.WindowBounds;
       }
    });
    

另請參閱