在COM組件中調用JavaScript函數
要求是很簡單的,即有COM組件A在IE中運行,使用JavaScript(JS)調用A的方法longCalc(),該方法是一個耗時的操作,要求通知IE當前的進度。這就要求使用回呼函數,設其名稱為scriptCallbackFunc。實現這個技術很簡單:
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;
}
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++客戶。
該技術和連接點、事件無關。
微軟的XML DOM對象廣泛使用這個方法。