嵌入式Web控件(IWebBrowser2),嵌入式javascript的onkeydown和onkeyup没有触发

时间:2011-05-05 21:14:25

标签: c++ windows iwebbrowser2

我在我的C ++程序中嵌入了一个网页。我遇到的问题是在嵌入式页面的javascript中我可以捕获onkeypress,但onkeydown和onkeyup不会触发。

如果我在非嵌入式IE(或Chrome)窗口中查看测试HTML,那么它可以完美运行。使用它嵌入IE控件时,这只是一个问题。

如果我为IE窗口挂钩WndProc(或使用Spy ++),WM_KEYDOWN,WM_CHAR和WM_KEYUP消息肯定会进入窗口。

我尝试尽可能减少示例代码 - 删除了大量错误检查,清理等等。

准备IE控件时是否有一些我缺少的设置?或者这就是使用IE嵌入式时的方式?我认为如果缺少设置,我就不会得到任何输入。

这是HTML测试文件:

<!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>

嵌入文件的C ++代码:

#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;
}

1 个答案:

答案 0 :(得分:1)

我知道这是一个相当老的线程,但我有完全相同的问题。

在我的情况下,错误是,我在Dialog类中覆盖了PreTranslateMessage(),但是没有调用CDialog :: PretranslateMessage(),而是从那里调用了CWnd :: PretranslateMessage()。