我正在我的 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;
}
最佳答案
我知道这是一个相当古老的话题,但我遇到了完全相同的问题。
在我的例子中,错误是我在我的 Dialog 类中覆盖了 PreTranslateMessage(),但我没有调用 CDialog::PretranslateMessage(),而是从那里调用了 CWnd::PretranslateMessage()。
关于c++ - 嵌入式 web 控件 (IWebBrowser2),嵌入式 javascript 的 onkeydown 和 onkeyup 不触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5904176/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
我有一个rubyonrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=