我在我的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;
}
IWebBrowser是一個複合窗口。你在Spy ++中看到了哪些窗口和你的消息? 我懷疑你需要明確地在瀏覽器窗口上激活/設置焦點。 – 2011-05-06 16:35:03
我玩弄明確設置焦點窗口無濟於事。此外 - 在我看來,這不是一個焦點問題,因爲我得到了按鍵事件。 – Aaron 2011-05-07 05:40:34