[为了更好的清晰度再次修改]
我有一个与网站交互的C++程序。该网站是只能在IE上使用的,我的程序也是如此。
我以一种普通方式(进程外 ——请参见代码)连接到正在运行的IE实例。一旦我获得了 IWebBrowser2
,我就可以毫无问题地获取 IHTMLDocument2
并与各个 IHTMLElement
对象进行交互,填写字段并单击按钮。
但如果网页有调用 window.showModalDialog 的javascript,那么我就卡住了:我需要像处理其他页面一样与弹出窗口中的HTML元素进行交互;但似乎我无法获取它的 IWebBrowser2
。
该弹出窗口始终标题为“Web Page Dialog”,是一个类型为 Internet Explorer_TridentDlgFrame
的窗口,其中包含一个 Internet Explorer_Server
。但是,我无法从 Internet Explorer_Server
窗口中获取 IWebBrowser2,就像处理普通IE实例时那样。
我可以获取 IHTMLDocument2Ptr
,但是当我尝试获取 IWebBrowser2
时,会返回一个 E_NOINTERFACE
的 HRESULT
。
代码非常标准,并且在处理“正常”的IE窗口时可以很好地工作。
IHTMLDocument2Ptr pDoc;
LRESULT lRes;
/* hWndChild is an instance of class "Internet Explorer_Server" */
UINT nMsg = ::RegisterWindowMessage( "WM_HTML_GETOBJECT" );
::SendMessageTimeout( hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000,
(DWORD*)&lRes );
LPFNOBJECTFROMLRESULT pfObjectFromLresult =
(LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, "ObjectFromLresult" );
if ( pfObjectFromLresult != NULL )
{
HRESULT hr;
hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)&pDoc );
if ( SUCCEEDED(hr) ) {
IServiceProvider *pService;
hr = pDoc->QueryInterface(IID_IServiceProvider, (void **) &pService);
if ( SUCCEEDED(hr) )
{
hr = pService->QueryService(SID_SWebBrowserApp,
IID_IWebBrowser2, (void **) &pBrowser);
// This is where the problem occurs:
// hr == E_NOINTERFACE
}
}
}
如果有关系的话,这是 Vista 和 IE8。(我强调这一点是因为这两个版本对我的代码库引入了破坏性的更改,而该代码库在 XP/IE7 中运行良好。)
再次强调,我的目标是获取每个 IHTMLElement
并与其交互。我无法访问我正在自动化的应用程序的源代码。
考虑到盲目地将按键发送到 Internet Explorer_Server
窗口,但我宁愿不这样做。
编辑添加:
有人建议获取子窗口并向其发送消息,但我相当确定这在 Internet Explorer_Server
上不起作用;根据 Spy++,没有任何子窗口。(这不是 IE 特定的。Java applet 似乎也没有子窗口。)
更新
在评论中,Simon Maurer 说上述代码对他有效,并且为了确保没有错别字,他非常慷慨地在 pastebin 上发布了一个完整的独立应用程序。当我使用他的代码时,在同样的位置以同样的方式失败,我意识到他认为我想连接到 底层 页面而不是弹出窗口。因此,我编辑了上面的文本,以消除这种歧义。
pDoc->QueryInterface
时,pDoc
看起来是否有效? - Nate Hekman