开发者

embedded web control (IWebBrowser2), embedded javascript's onkeydown and onkeyup not firing

I'm embedding a web page within my C++ program. The problem that I'm running into is that within javascript of the embedded page I can capture onkeypress, but onkeydown and onkeyup don't fire.

If I view the test HTML in a non-embedded IE (or Chrome) window then it works perfectly. It's only a problem when using it embedded in an IE control.

If I hook the WndProc for the IE window (or use Spy++) the WM_KEYDOWN, WM_CHAR and WM_KEYUP messages are definately making it to the window.

I tried to make the example code as minimal as possible - removed a lot of error checking, clean up, etc.

Is there some setup that I'm missing when preparing the IE control? Or is this just the way it is when using IE embedded? I would think that if it was missing setup I wouldn't get ANY input.

Here's the HTML test file:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <script type="text/javascript" language="javascript">
            var n = 0;
            document.onkeydown = function()
            {
              var output=document.getElementById("output");
              output.innerHTML = n++ + " onkeydown<br>" + output.innerHTML;
              return true;
            };
            document.onkeypress = function()
            {
              var output=document.getElementById("output");
              output.innerHTML = n++ + " onkeypress<br>" + output.innerHTML;
              return true;
            };
            document.onkeyup = function()
            {
              var output=document.getElementById("output");
              output.innerHTML = n++ + " onkeyup<br>" + output.innerHTML;
              return true;
            };
        </script>
  </head>
  <body>
        This is some testing text.
        <input/>
        <br>
        <div id="output" style="border-style:solid; border-width:1; "></div>
    </body>
</html>

And the C++ code to embed the file:

#include <stdio.h>
#include <Windows.h>
#include <string>
#include <atlbase.h> // for CComPtr<>
#include <Exdisp.h>
#include <comdef.h> // for variant_t

namespace
{
    const int MAIN_WINDOW_WIDTH = 800;
    const int MAIN_WINDOW_HEIGHT = 600;

    const int HTML_WINDOW_WIDTH = 640;
    const int HTML_WINDOW_HEIGHT = 480;
}

//------------------------------------------------------------------------------

void FatalError(std::string _report)
{
    ::MessageBox(nullptr, _report.c_str(), "Error", MB_OK);
    ::ExitProcess(1);
}

//------------------------------------------------------------------------------

class EmbeddedBrowser :
    public IOleClientSite,
    public IOleInPlaceSite,
    public IStorage
{
public:
    EmbeddedBrowser(HWND _mainWindow)
    {
        m_comRefCount = 0;
        ::SetRect(&m_objectRect, -300, -300, 300, 300);
        m_mainWindow = _mainWindow;

        CreateBrowserObject();

        ::ShowWindow(GetControlWindow(), SW_SHOW);

        variant_t flags((UINT)0);
        m_webBrowser->Navigate(L"about:blank",
            &flags, nullptr, nullptr, nullptr);
    }


    void CreateBrowserObject()
    {
        HRESULT hr = ::OleCreate(CLSID_WebBrowser,
            IID_IOleObject, OLERENDER_DRAW, 0, this, this, (void**)&m_oleObject);
        if(FAILED(hr))
            FatalError("OleCreate() failed");

        hr = m_oleObject->SetClientSite(this);
        hr = OleSetContainedObject(m_oleObject, TRUE);

        RECT posRect;
        ::SetRect(&posRect, -300, -300, 300, 300);
        hr = m_oleObject->DoVerb(OLEIVERB_INPLACEACTIVATE,
            NULL, this, -1, m_mainWindow, &posRect);
        if(FAILED(hr))
            FatalError("DoVerb(OLEIVERB_INPLACEACTIVATE) failed");

        hr = m_oleObject.QueryInterface(&m_webBrowser);
        if(FAILED(hr))
            FatalError("QueryInterface(IWebBrowser) failed");
    }


    virtual void Navigate(std::wstring _url)
    {
        bstr_t url(_url.c_str());
        variant_t flags(0x02u); // navNoHistory;
        HRESULT hr = m_webBrowser->Navigate(url,
            &flags, nullptr, nullptr, nullptr);
    }


    RECT PixelToHiMetric(const RECT& _rc)
    {
        static bool s_initialized = false;
        static int s_pixelsPerInchX, s_pixelsPerInchY;
        if(!s_initialized)
        {
            HDC hdc = ::GetDC(nullptr);
            s_pixelsPerInchX = ::GetDeviceCaps(hdc, LOGPIXELSX);
            s_pixelsPerInchY = ::GetDeviceCaps(hdc, LOGPIXELSY);
            ::ReleaseDC(nullptr, hdc);
            s_initialized = true;
        }

        RECT rc;
        rc.left = MulDiv(2540, _rc.left, s_pixelsPerInchX);
        rc.top = MulDiv(2540, _rc.top, s_pixelsPerInchY);
        rc.right = MulDiv(2540, _rc.right, s_pixelsPerInchX);
        rc.bottom = MulDiv(2540, _rc.bottom, s_pixelsPerInchY);
        return rc;
    }


    virtual void SetRect(const RECT& _rc)
    {
        m_objectRect = _rc;

        {
            RECT hiMetricRect = PixelToHiMetric(m_objectRect);
            SIZEL sz;
            sz.cx = hiMetricRect.right - hiMetricRect.left;
            sz.cy = hiMetricRect.bottom - hiMetricRect.top;
            m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
        }

        if(m_oleInPlaceObject != nullptr)
        {
            m_oleInPlaceObject->SetObjectRects(&m_objectRect, &m_objectRect);
        }
    }

    // ----- IUnknown -----

    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void**ppvObject) override
    {
        if(riid == __uuidof(IUnknown))
        { (*ppvObject) = static_cast<IOleClientSite*>(this); }
        else if(riid == __uuidof(IOleInPlaceSite))
        { (*ppvObject) = static_cast<IOleInPlaceSite*>(this); }
        else
        {
            return E_NOINTERFACE;
        }

        AddRef(); // implicit AddRef()
        return S_OK;
    }

    virtual ULONG STDMETHODCALLTYPE AddRef( void) override
    {
        m_comRefCount++; 
        return m_comRefCount;
    }


    virtual ULONG STDMETHODCALLTYPE Release( void) override
    { 
        m_comRefCount--;
        return m_comRefCount;
    }

    // ---------- IOleWindow ----------

    virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetWindow( 
        /* [out] */ __RPC__deref_out_opt HWND *phwnd) override
    {
        (*phwnd) = m_mainWindow;
        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp( 
        /* [in] */ BOOL fEnterMode) override
    {
        return E_NOTIMPL;
    }

    // ---------- IOleInPlaceSite ----------

    virtual HRESULT STDMETHODCALLTYPE CanInPlaceActivate( void) override
    {
        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE OnInPlaceActivate( void) override
    {
        OleLockRunning(m_oleObject, TRUE, FALSE);
        m_oleObject.QueryInterface(&m_oleInPlaceObject);
        开发者_高级运维m_oleInPlaceObject->SetObjectRects(&m_objectRect, &m_objectRect);

        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE OnUIActivate( void) override
    {
        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE GetWindowContext( 
        /* [out] */ __RPC__deref_out_opt IOleInPlaceFrame **ppFrame,
        /* [out] */ __RPC__deref_out_opt IOleInPlaceUIWindow **ppDoc,
        /* [out] */ __RPC__out LPRECT lprcPosRect,
        /* [out] */ __RPC__out LPRECT lprcClipRect,
        /* [out][in] */ __RPC__inout LPOLEINPLACEFRAMEINFO lpFrameInfo) override
    {
        HWND hwnd = m_mainWindow;

        (*ppFrame) = NULL;
        (*ppDoc) = NULL;
        (*lprcPosRect).left = m_objectRect.left;
        (*lprcPosRect).top = m_objectRect.top;
        (*lprcPosRect).right = m_objectRect.right;
        (*lprcPosRect).bottom = m_objectRect.bottom;
        *lprcClipRect = *lprcPosRect;

        lpFrameInfo->fMDIApp = false;
        lpFrameInfo->hwndFrame = hwnd;
        lpFrameInfo->haccel = NULL;
        lpFrameInfo->cAccelEntries = 0;

        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE Scroll( 
        /* [in] */ SIZE scrollExtant) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE OnUIDeactivate( 
        /* [in] */ BOOL fUndoable) override
    {
        return S_OK;
    }

    virtual HWND GetControlWindow()
    {
        if(m_controlWindow != nullptr)
            return m_controlWindow;

        if(m_oleInPlaceObject == nullptr)
            return nullptr;

        m_oleInPlaceObject->GetWindow(&m_controlWindow);
        return m_controlWindow;
    }

    virtual HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate( void) override
    {
        m_controlWindow = nullptr;
        m_oleInPlaceObject = nullptr;

        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE DiscardUndoState( void) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE DeactivateAndUndo( void) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE OnPosRectChange( 
        /* [in] */ __RPC__in LPCRECT lprcPosRect) override
    {
        return E_NOTIMPL;
    }

    // ---------- IOleClientSite ----------

    virtual HRESULT STDMETHODCALLTYPE SaveObject( void) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE GetMoniker( 
        /* [in] */ DWORD dwAssign,
        /* [in] */ DWORD dwWhichMoniker,
        /* [out] */ __RPC__deref_out_opt IMoniker **ppmk) override
    {
        if((dwAssign == OLEGETMONIKER_ONLYIFTHERE) &&
           (dwWhichMoniker == OLEWHICHMK_CONTAINER))
            return E_FAIL;

        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE GetContainer( 
        /* [out] */ __RPC__deref_out_opt IOleContainer **ppContainer) override
    {
        return E_NOINTERFACE;
    }

    virtual HRESULT STDMETHODCALLTYPE ShowObject( void) override
    {
        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE OnShowWindow( 
        /* [in] */ BOOL fShow) override
    {
        return S_OK;
    }

    virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout( void) override
    {
        return E_NOTIMPL;
    }

    // ----- IStorage -----

    virtual HRESULT STDMETHODCALLTYPE CreateStream( 
        /* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
        /* [in] */ DWORD grfMode,
        /* [in] */ DWORD reserved1,
        /* [in] */ DWORD reserved2,
        /* [out] */ __RPC__deref_out_opt IStream **ppstm) override
    {
        return E_NOTIMPL;
    }

    virtual /* [local] */ HRESULT STDMETHODCALLTYPE OpenStream( 
        /* [string][in] */ const OLECHAR *pwcsName,
        /* [unique][in] */ void *reserved1,
        /* [in] */ DWORD grfMode,
        /* [in] */ DWORD reserved2,
        /* [out] */ IStream **ppstm) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE CreateStorage( 
        /* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
        /* [in] */ DWORD grfMode,
        /* [in] */ DWORD reserved1,
        /* [in] */ DWORD reserved2,
        /* [out] */ __RPC__deref_out_opt IStorage **ppstg) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE OpenStorage( 
        /* [string][unique][in] */ __RPC__in_opt_string const OLECHAR *pwcsName,
        /* [unique][in] */ __RPC__in_opt IStorage *pstgPriority,
        /* [in] */ DWORD grfMode,
        /* [unique][in] */ __RPC__deref_opt_in_opt SNB snbExclude,
        /* [in] */ DWORD reserved,
        /* [out] */ __RPC__deref_out_opt IStorage **ppstg) override
    {
        return E_NOTIMPL;
    }

    virtual /* [local] */ HRESULT STDMETHODCALLTYPE CopyTo( 
        /* [in] */ DWORD ciidExclude,
        /* [size_is][unique][in] */ const IID *rgiidExclude,
        /* [annotation][unique][in] */ 
        __RPC__in_opt  SNB snbExclude,
        /* [unique][in] */ IStorage *pstgDest) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE MoveElementTo( 
        /* [string][in] */ __RPC__in_string const OLECHAR *pwcsName,
        /* [unique][in] */ __RPC__in_opt IStorage *pstgDest,
        /* [string][in] */ __RPC__in_string const OLECHAR *pwcsNewName,
        /* [in] */ DWORD grfFlags) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE Commit( 
        /* [in] */ DWORD grfCommitFlags) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE Revert( void) override
    {
        return E_NOTIMPL;
    }

    virtual /* [local] */ HRESULT STDMETHODCALLTYPE EnumElements( 
        /* [in] */ DWORD reserved1,
        /* [size_is][unique][in] */ void *reserved2,
        /* [in] */ DWORD reserved3,
        /* [out] */ IEnumSTATSTG **ppenum) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE DestroyElement( 
        /* [string][in] */ __RPC__in_string const OLECHAR *pwcsName) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE RenameElement( 
        /* [string][in] */ __RPC__in_string const OLECHAR *pwcsOldName,
        /* [string][in] */ __RPC__in_string const OLECHAR *pwcsNewName) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE SetElementTimes( 
        /* [string][unique][in] */ __RPC__in_opt_string const OLECHAR *pwcsName,
        /* [unique][in] */ __RPC__in_opt const FILETIME *pctime,
        /* [unique][in] */ __RPC__in_opt const FILETIME *patime,
        /* [unique][in] */ __RPC__in_opt const FILETIME *pmtime) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE SetClass( 
        /* [in] */ __RPC__in REFCLSID clsid) override
    {
        return S_OK;
        //return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE SetStateBits( 
        /* [in] */ DWORD grfStateBits,
        /* [in] */ DWORD grfMask) override
    {
        return E_NOTIMPL;
    }

    virtual HRESULT STDMETHODCALLTYPE Stat( 
        /* [out] */ __RPC__out STATSTG *pstatstg,
        /* [in] */ DWORD grfStatFlag) override
    {
        return E_NOTIMPL;
    }

private:
protected:
    CComPtr<IOleObject> m_oleObject;
    LONG m_comRefCount;
    HWND m_mainWindow;
    RECT m_objectRect;
    CComPtr<IWebBrowser2> m_webBrowser;
    CComPtr<IOleInPlaceObject> m_oleInPlaceObject;
    HWND m_controlWindow;
};

//------------------------------------------------------------------------------

void EventLoop(HWND _mainWindow)
{
    while(IsWindow(_mainWindow))
    {
        MSG msg;
        if(GetMessage(&msg, nullptr, 0, 0) <= 0)
            break;
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}


int main(int argc, char* argv[])
{
    OleInitialize(nullptr);

    WNDCLASS wc;
    memset(&wc, 0, sizeof(wc));
    wc.lpszClassName = "MyWindowClass";
    wc.lpfnWndProc = DefWindowProc;
    wc.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
    RegisterClass(&wc);

    HWND mainWindow = CreateWindow("MyWindowClass",
        "My Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT,
        CW_USEDEFAULT, MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT, nullptr,
        nullptr, nullptr, nullptr);

    RECT rc;
    rc.left = (MAIN_WINDOW_WIDTH - HTML_WINDOW_WIDTH) / 2;
    rc.top = (MAIN_WINDOW_HEIGHT - HTML_WINDOW_HEIGHT) / 2;
    rc.right = rc.left + HTML_WINDOW_WIDTH;
    rc.bottom = rc.top + HTML_WINDOW_HEIGHT;

    wchar_t navUrl[MAX_PATH];
    ::GetCurrentDirectoryW(MAX_PATH, navUrl);
    wcscat_s(navUrl, L"\\test.html");

    EmbeddedBrowser* browser = new EmbeddedBrowser(mainWindow);
    browser->SetRect(rc);
    browser->Navigate(navUrl);

    EventLoop(mainWindow);

    ExitProcess(0);

    return 0;
}


I know this is a rather old thread, but I had the exactly same Problem.

In my case the error was, that I overwrote PreTranslateMessage() in my Dialog class, but instead of calling CDialog::PretranslateMessage() I called CWnd::PretranslateMessage() from there.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜