Java实现与IE的交互

[size=medium][b]需求[/b][/size]
遍历当前打开的IE实例,分别获取IE浏览器中打开文档的一个节点值,调用IE内容中的一个javascript函数。

[size=medium][b]分析[/b][/size]
Java直接控制IE浏览器,有点麻烦。只有通过VC来实现,生成一个dll文件,Java通过JNI调用。

[size=medium][b]实现:[/b][/size]

1、准备工作:该工程采用的原理是通过和IE对象的接口的交互来实现对IE的访问,实际上是采用COM的技术。所以需要在vc工程中加入对COM的支持:
#import <shdocvw.dll>
#import <mshtml.tlb> // Internet Explorer 5
#include <atlbase.h>
CComModule _Module;// 由于要使用 CComDispatchDriver ATL的智能指针,
// 所以声明它是必须的

#include <mshtml.h> // 所有 IHTMLxxxx 的接口声明
#include <atlcom.h>


2、用VC实现对当前IE实例的进行遍历的方法,通过ShellWindows集合来代表属于shell的当前打开的窗口的集合,而IE就是属于shell的一个应用程序。

CoInitialize(NULL);//初始化COM
CComPtr< IShellWindows > spShellWin;
HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
if ( FAILED ( hr ) )
{
return;
}

long nCount = 0;
spShellWin->get_Count( &nCount );// 取得浏览器实例个Explorer
//和 IExplorer)
if( 0 == nCount )
{
return;
}

for(int i=0; i<nCount; i++)
{
CComPtr< IDispatch > spDispIE;
hr=spShellWin->Item(CComVariant( (long)i ), &spDispIE );
if ( FAILED ( hr ) ) continue;

CComQIPtr< IWebBrowser2 > spBrowser = spDispIE;
if ( !spBrowser ) continue;

CComPtr < IDispatch > spDispDoc;
hr = spBrowser->get_Document( &spDispDoc );//判断实例
//对象是不是属于IE浏览器对象

if ( FAILED ( hr ) ) continue;
ComQIPtr< IHTMLDocument2 > spDocument2 = spDispDoc;
if ( !spDocument2 ) continue;
// 程序运行到此,已经找到了 IHTMLDocument2 的接口指针
}
CoUninitialize();//release COM


3、获取IE浏览器中打开文档的一个节点值

HRESULT hr;
CComBSTR bstrTitle;
CComPtr<IHTMLElementCollection> pElementCol;
VARIANT id, index;
CComPtr<IHTMLElement> pElement;
pIHTMLDocument2->get_title( &bstrTitle ); //取得文档标题
if (SUCCEEDED(pIHTMLDocument2->get_all(&pElementCol)))
{
long p=0;
if(SUCCEEDED(pElementCol->get_length(&p)))
if(p!=0)
{
// AfxMessageBox("1");
for(long i=0;i<=(p-1);i++)
{

V_VT(&id) = VT_I4;
V_I4(&id) = i;
V_VT(&index) = VT_I4;
V_I4(&index) = 0;

if(SUCCEEDED(pElementCol->item(id,index, &spDispatch)))
{

if(SUCCEEDED(spDispatch->QueryInterface(IID_IHTMLElement,(void**)&pElement)))
{
CComBSTR value;
CComBSTR type;
pElement->get_outerText(&value);
pElement->get_tagName(&type);
CString str(value);
CString str2(type);
if(str == "百度一下,你就知道")
AfxMessageBox(str);
if(str2 == "BROWERID")
AfxMessageBox(str2);
}
}
}
}
}


4、调用IE内容中的一个javascript函数

HRESULT ExecJavascript(CString strJsFunctionName_In, const CArray <VARIANT, VARIANT&> &pArrVARIANT_Params)
{
//前提是你已经取得了IHTMLDocument2
//(1)Get Script
CComPtr <IDispatch> pScript;

hResult = m_IHTMLDocument2-> get_Script(&pScript);
if(FAILED(hResult))
{
return FALSE;
}

//(2)Get Javascript Function
CComBSTR pCComBSTR(strJsFunctionName_In);
DISPID pDISPID;
hResult = pScript-> GetIDsOfNames(IID_NULL, &pCComBSTR, 1, LOCALE_SYSTEM_DEFAULT, &pDISPID);
if(FAILED(hResult))
{
return FALSE;
}

//(3)Add Parameters
DISPPARAMS pDISPPARAMS;
memset(&pDISPPARAMS, 0, sizeof(pDISPPARAMS));

int intArgsCount_In = pArrVARIANT_Params.GetSize();
VARIANT* vParams = new VARIANT[intArgsCount_In];

for( int i = 0; i < intArgsCount_In; i++)
{
vParams[i] = pArrVARIANT_Params.GetAt(i);
}

//Params Count
pDISPPARAMS.cArgs = intArgsCount_In;
//Params Array
pDISPPARAMS.rgvarg = vParams;
//Name Args Count
pDISPPARAMS.cNamedArgs = 0;

//(4)Invoke Javascript Method
EXCEPINFO pEXCEPINFO;
memset(&pEXCEPINFO, 0, sizeof(pEXCEPINFO));

CComVariant pCComVariant;

//Initialize to invalid arg
UINT nintArgErr = (UINT)-1;

hResult = pScript-> Invoke
(pDISPID, IID_NULL, 0, DISPATCH_METHOD, &pDISPPARAMS, &pCComVariant, &pEXCEPINFO, &nintArgErr);

delete[] pDISPPARAMS.rgvarg;
pScript.Release();

if(FAILED(hResult))
{
return FALSE;
}

return TRUE;
}


5、编译生成dll文件,供Java通过JNI调用

[size=medium][b]注意事项[/b][/size]
1、可能Java通过JNI调用的时候,会报异常,可能是因为没有释放一些资源包括IDispatch、IHTMLElementCollection、IHTMLElement等。c++不会像java那样垃圾自动回收,需要手动释放。
2、首先需要调用CoInitialize(NULL),因为在调用任何COM函数之前,需要一个线程去调用CoInitialize(NULL)来加载COM组件,这样就可以自由地调用COM的,不过不要忘记CoUninitialize()哦!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值