本文详解在IE环境中,C++编写的COM组件如何通过IDispatch接口调用JavaScript回调函数。通过传递VARIANT参数,组件可异步通知JS当前执行进度,适用于耗时操作的状态反馈。
COM组件调用JavaScript回调函数详解
COM组件中调用JavaScript函数详解及实例
需求场景较为直接:在Internet Explorer浏览器中运行一个COM组件A,并通过JavaScript调用其方法longCalc()。由于该方法执行时间较长,需要向IE反馈当前的处理进度。为此,需引入回调机制,设定回调函数名为scriptCallbackFunc。实现这一功能的技术路径如下:
C++组件端实现
1 、组件方(C++)
组件A的方法需在接口定义语言(IDL)中进行声明:
[id(2)] HRESULT longCalc([in] DOUBLE v1, [in] DOUBLE v2, [in, optional] VARIANT scriptCallback);
组件A的具体实现逻辑如下:
// 假设回调原型为:
// scriptCallbackFunc(LONG nCurrentProgress, LONG nTotalProgress, BSTR bstrProgressName);
// 此方法由JS脚本来实现
STDMETHODIMP CA:: longCalc (DOUBLE v1, DOUBLE v2, VARIANT scriptCallback)
{
CComPtr<IDispatch> spCallback;
if (scriptCallback.vt == VT_DISPATCH)
spCallback = scriptCallback.pdispVal;
// 参数准备
CComVariant varResult;
CComVariant avarParams[3];
avarParams[0] = “开始计算股票”; // bstrProgressName
avarParams[0].vt = VT_BSTR;
avarParams[1] = 100; // nTotalProgress
avarParams[1].vt = VT_I4;
avarParams[2] = 0; // nCurrentProgress
avarParams[2].vt = VT_I4;
DISPPARAMS params = { avarParams, NULL, 3, 0 };
if(spCallback)
spCallback->Invoke(0,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
¶ms, &varResult, NULL, NULL);
BOOL bFinished = false;
while(!bFinished)
{
// 计算工作…
Sleep(1000);
v1 = v1+v2;
// 回调客户
if(spCallback)
{
avarParams[0] = “正在计算股票…”;
avarParams[2] = 0;
spCallback->Invoke(0,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
¶ms, &varResult, NULL, NULL);
}
if(…)
bFinished = TRUE;
} // while OK!
return S_OK;
}
JavaScript客户端实现
2、 客户方(JS)
<script language="javascript">
<!--
// 符合回调原型:scriptCallbackFunc
function scfDisplayProgress(nCurrentProgress, nTotalProgress, bstrProgressName)
{
window.status = bstrProgressName + “:”+(nCurrentProgress *100/TotalProgress);
}
// 创建组件并执行longCalc
var objA = new ActiveXObject(“MyCom.A”);
// 使用回调: 执行时在IE状态栏显示进度
objA. longCalc (100, 200, scfDisplayProgress);
// 不使用回调
objA. longCalc (100, 200);
//-->
</script>
技术要点说明
3 说明
- 该技术方案仅适用于脚本环境,不适用于VB或C++等客户端程序。
- 此实现方式与COM连接点(Connection Points)及事件机制无直接关联。
- 微软的XML DOM对象广泛采用此类回调机制。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!