2

我有一个 COM STA,它承载一个 ICoreWebView2。

我尝试获取完整的 HTML 块,并找到了一个文档来使用脚本实现这一点。这是我的代码:

    hr = m_spWebView->ExecuteScript(L"document.body.outerHTML",
        Callback<ICoreWebView2ExecuteScriptCompletedHandler>(
            [&val](HRESULT hr, LPCWSTR result) -> HRESULT 
            {
                if (SUCCEEDED(hr))
                    val = result;
                return S_OK;
            }
        ).Get()
    );

此代码有效,但它是异步执行的。所以需要一些时间才能得到结果。事实上,我可以看到结果在下一次执行消息泵时到达(正如我对 STA 的预期)。

在 C# 中,我会使用 await 来等待完成。但是使用 C++ 没有这样的东西。使用事件是行不通的,因为我有一个 STA,我会阻塞线程并且答案永远不会到达。

有什么方法可以调用等待 C++ 完成的函数?或者另一个帮助是使用ExecuteScript同步。

4

2 回答 2

0

您必须实现 IDispatch 接口(COM stuf),并添加它:

m_spWebView->AddHostObjectToScript(L"host", &disp);

然后在加载文档时让 JavaScript 调用它。

struct CDispatch : IDispatch
{
...
} cdisp;

您将在 Invoke 调用中将 HTML 作为参数获取。不需要担心其他方法,只需在 QueryInterface 中确认 IID_IDispatch 并注意 Invoke。

 window.chrome.webview.hostObjects.host(document.body.outerHTML);

我在这里尝试并设法做你愿意做的事情。

于 2020-12-04T03:32:11.307 回答
-1

如果您有一个 STA,那么您可以启动您的消息循环或返回并允许您的消息循环继续处理消息,而不是显式等待完成。

如果您需要在不返回消息循环的情况下阻止执行和处理消息,您可以尝试使用CoWaitForMultipleHandleswithCOWAIT_DISPATCH_WINDOW_MESSAGES来确保您处理执行 WebView2 回调所必需的窗口消息。但是,这可能会使您的应用程序面临重入或其他同步问题,并且取决于您应用程序的其余部分如何处理此问题,这可能是一个问题。

通常,更好的解决方案是返回到您的消息循环。

于 2020-10-21T19:54:01.647 回答