2011-05-05 64 views
3

我在我的C++程序中嵌入了一個網頁。我遇到的問題是,在嵌入式頁面的JavaScript內部,我可以捕獲onkeypress,但onkeydown和onkeyup不會觸發。嵌入式Web控件(IWebBrowser2),嵌入式JavaScript的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; 
} 
+0

IWebBrowser是一個複合窗口。你在Spy ++中看到了哪些窗口和你的消息? 我懷疑你需要明確地在瀏覽器窗口上激活/設置焦點。 – 2011-05-06 16:35:03

+0

我玩弄明確設置焦點窗口無濟於事。此外 - 在我看來,這不是一個焦點問題,因爲我得到了按鍵事件。 – Aaron 2011-05-07 05:40:34

回答

1

我知道這是一個相當古老的線程,但我有完全相同的問題。

在我的情況下,錯誤是,我重寫了我的Dialog類中的PreTranslateMessage(),但不是從那裏調用CDialog :: PretranslateMessage(),而是從那裏調用CWnd :: PretranslateMessage()。