兄弟帮忙看一段获取IHTMLDocument2接口的代码,MSDN上面找的,该怎么处理
兄弟帮忙看一段获取IHTMLDocument2接口的代码,MSDN上面找的
原本是想获取INTERNET EXPLORER_SERVER里面的文本,用了下面这个函数,获取接口正常,但一使用接口就出错。后来我直接尝试获取接口的原函数,还是不行,执行到spDoc->put_bgColor( CComVariant("red") );这一行就死掉了,麻烦高手帮我看一下,下面是我在MSDN上面找到的代码,一起贴上来,
还有说一下我用的是WIN7+VS2008,IE的窗口句柄是直接用Spy++得到的,
BOOL CALLBACK MyEnumChildProc(HWND hwnd,LPARAM lParam)
{
TCHAR buf[100];
::GetClassName( hwnd, (LPTSTR)&buf, 100 );
if ( _tcscmp( buf, _T("Internet Explorer_Server") ) == 0 )
{
*(HWND*)lParam = hwnd;
return FALSE;
}
else
return TRUE;
}
void OnGetDocInterface(HWND hWnd)
{
CoInitialize( NULL );
// Explicitly load MSAA so we know if it's installed
HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );
if ( hInst != NULL )
{
if ( hWnd != NULL )
{
HWND hWndChild=NULL;
// Get 1st document window
::EnumChildWindows( hWnd, MyEnumChildProc, (LPARAM)&hWndChild );
if ( hWndChild )
{
CComPtr<IHTMLDocument2> spDoc;
LRESULT lRes;
UINT nMsg = ::RegisterWindowMessage( _T("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**)&spDoc );
if ( SUCCEEDED(hr))
{
// Change background color to red
spDoc->put_bgColor( CComVariant("red") );
}
}
} // else document not ready
} // else Internet Explorer is not running
::FreeLibrary( hInst );
} // else Active Accessibility is not installed
CoUninitialize();
}
------解决方案--------------------
ObjectFromLresult 仅限项目内部使用,MSDN的解释:Neither clients nor servers should call this function.
实际上这个API本来不应该公开,它只能用于当前线程中创建的组件,跨线程不能用,跨进程更不用说。
------解决方案--------------------
事实上,这种方法是可以用的,获取【其他进程】的doc进行操作没有任何问题!
我曾经用这种方法写过一个自动玩qq网页游戏怪物对对碰的辅助工具(使用IE打开qq怪物对对碰游戏,然后用工具选中该IE窗口,就可以自动玩)
原本是想获取INTERNET EXPLORER_SERVER里面的文本,用了下面这个函数,获取接口正常,但一使用接口就出错。后来我直接尝试获取接口的原函数,还是不行,执行到spDoc->put_bgColor( CComVariant("red") );这一行就死掉了,麻烦高手帮我看一下,下面是我在MSDN上面找到的代码,一起贴上来,
还有说一下我用的是WIN7+VS2008,IE的窗口句柄是直接用Spy++得到的,
BOOL CALLBACK MyEnumChildProc(HWND hwnd,LPARAM lParam)
{
TCHAR buf[100];
::GetClassName( hwnd, (LPTSTR)&buf, 100 );
if ( _tcscmp( buf, _T("Internet Explorer_Server") ) == 0 )
{
*(HWND*)lParam = hwnd;
return FALSE;
}
else
return TRUE;
}
void OnGetDocInterface(HWND hWnd)
{
CoInitialize( NULL );
// Explicitly load MSAA so we know if it's installed
HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );
if ( hInst != NULL )
{
if ( hWnd != NULL )
{
HWND hWndChild=NULL;
// Get 1st document window
::EnumChildWindows( hWnd, MyEnumChildProc, (LPARAM)&hWndChild );
if ( hWndChild )
{
CComPtr<IHTMLDocument2> spDoc;
LRESULT lRes;
UINT nMsg = ::RegisterWindowMessage( _T("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**)&spDoc );
if ( SUCCEEDED(hr))
{
// Change background color to red
spDoc->put_bgColor( CComVariant("red") );
}
}
} // else document not ready
} // else Internet Explorer is not running
::FreeLibrary( hInst );
} // else Active Accessibility is not installed
CoUninitialize();
}
------解决方案--------------------
ObjectFromLresult 仅限项目内部使用,MSDN的解释:Neither clients nor servers should call this function.
实际上这个API本来不应该公开,它只能用于当前线程中创建的组件,跨线程不能用,跨进程更不用说。
------解决方案--------------------
事实上,这种方法是可以用的,获取【其他进程】的doc进行操作没有任何问题!
我曾经用这种方法写过一个自动玩qq网页游戏怪物对对碰的辅助工具(使用IE打开qq怪物对对碰游戏,然后用工具选中该IE窗口,就可以自动玩)
- C/C++ code
HRESULT CMyQQGameToolDlg::GetIHTMLDocument2FromHWND(IHTMLDocument2 ** pDoc2) { LRESULT lRes; UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") ); ::SendMessageTimeout(m_hIE, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes ); LPFNOBJECTFROMLRESULT pfObjectFromLresult = (LPFNOBJECTFROMLRESULT)::GetProcAddress( m_hInstMSAA, "ObjectFromLresult"); if (NULL == pfObjectFromLresult) { ... } HRESULT hr; hr = (*pfObjectFromLresult)( lRes, IID_IHTMLDocument, 0, (void**)pDoc2 ); if (FAILED(hr)) { ... } return S_OK; } 调用处的代码 // GET IE hwnd ... CComPtr<IHTMLDocument2> spDoc2; HRESULT hr = E_FAIL; hr = GetIHTMLDocument2FromHWND(&spDoc2); ///////////////////////////////////////////////////// // 直接操作spDoc2会有异常! // 再QI一次获取另外的接口就可以操作了 // CComQIPtr<IHTMLDocument3> spDoc3 = spDoc2; hr = spDoc3->getElementById(...