Search code examples
visual-c++contextmenuwebview2

WebView2 - Viewing Page Source via Context Menu in popup window


I know that there are several questions around the theme of page source but they don't seem related to my issue. I have also asked this question on the WebView2 GitHub website but it was closed.

Goal

I have an embedded WebView2 control on my CDialog and I am implementing a custom menu. I want to be able to view the page source and it should show in a popup. In-fact, it should show exactly as when you press CTRL + U in the browser control: enter image description here

Issue

I added the following custom menu event handler to display the page source:

// ===============================================================
wil::com_ptr<ICoreWebView2ContextMenuItem> itemViewPageSource;
CHECK_FAILURE(webviewEnvironment->CreateContextMenuItem(
    L"View Page Source (CTRL + U)", nullptr,
    COREWEBVIEW2_CONTEXT_MENU_ITEM_KIND_COMMAND, &itemViewPageSource));

CHECK_FAILURE(itemViewPageSource->add_CustomItemSelected(
    Callback<ICoreWebView2CustomItemSelectedEventHandler>(
        [appWindow = this, target](ICoreWebView2ContextMenuItem* sender, IUnknown* args)
        {
            wil::unique_cotaskmem_string pageUri;
            CHECK_FAILURE(target->get_PageUri(&pageUri));
            CString strUrl = L"view-source:" + CString(pageUri.get());

            appWindow->NavigateTo(strUrl);
            //appWindow->m_pImpl->m_webView->ExecuteScript(L"window.open(\"" + CString(pageUri.get()) + L"\", \"\", \"width=300, height=300\")", nullptr);

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

CHECK_FAILURE(items->InsertValueAtIndex(itemsCount, itemViewPageSource.get()));
itemsCount++;
// ===============================================================

The problem is that the source is not displayed in a new popup window (like when using the hotkey):

enter image description here

Update 1

I was able to change the code to use some JavaScript to display the page itself in a new window:

 appWindow->m_pImpl->m_webView->ExecuteScript(L"window.open(\"" + CString(pageUri.get()) + L"\", \"\", \"width=300, height=300\")", nullptr);

And then, when I tried CTRL + U on the popup window, it appeared to display the source in the same window. But in actual fact it was a new window, as I could move it:

enter image description here

At this time I have not found out how to display the page source in a popup-up window (given teh context of my browser control) just like when you press CTRL + U.


Solution

  • The easiest way to do this is why the SendInput API:

    CHECK_FAILURE(itemViewPageSource->add_CustomItemSelected(
        Callback<ICoreWebView2CustomItemSelectedEventHandler>(
            [appWindow = this, target](ICoreWebView2ContextMenuItem* sender, IUnknown* args)
            {
                wil::unique_cotaskmem_string pageUri;
                CHECK_FAILURE(target->get_PageUri(&pageUri));
                CString strUrl = L"view-source:" + CString(pageUri.get());
    
                // Create an array of generic keyboard INPUT structures
                INPUT ip[4] = {};
                for (int n = 0; n < 4; ++n)
                {
                    ip[n].type = INPUT_KEYBOARD;
                    ip[n].ki.wScan = 0;
                    ip[n].ki.time = 0;
                    ip[n].ki.dwFlags = 0; // 0 for key press
                    ip[n].ki.dwExtraInfo = 0;
                }
    
                ip[0].ki.wVk = VK_CONTROL;
                ip[1].ki.wVk = 'U';
    
                ip[2].ki.wVk = 'U';
                ip[2].ki.dwFlags = KEYEVENTF_KEYUP;
    
                ip[3].ki.wVk = VK_CONTROL;
                ip[3].ki.dwFlags = KEYEVENTF_KEYUP;
    
                SendInput(4, ip, sizeof(INPUT));
                
                return S_OK;
            })
        .Get(), nullptr));
    
    CHECK_FAILURE(items->InsertValueAtIndex(itemsCount, itemViewPageSource.get()));
    itemsCount++;