描述:
问一个嵌入html的activex控件的问题:
当activex完成任务后, 希望能通过某种方式通告给调用控件的页面, 以便页面自动刷新
当前做的代码是一个mfc activex控件, 请问有这种机制吗
解决方案1:
html:
<object classid="clsid:C0F1EDF0-34C3-4300-A322-4B94CCE40B85" id="XXXBrowser"
codebase="http://notebook/Test/XXXBrowser.cab" width=100% height=100%>
<param name="_ExtentY" value="20320">
<param name="_StockProps" value="0">
</object>
</p>
<script language=JScript for=XXXBrowser event="Logs(iType,strInfo)">
alert(iType);
alert(strInfo);
</script>
Logs(iType,strInfo)为ActiveX控件定义的Automation事件。
有啊,给你代码
CString CXXXCtrl::PageInterface(long lParam1, long lParam2, long lParam3, const CString& strParam)
{
HRESULT hr = E_FAIL;
CComPtr<IOleObject> pOleObject = 0;
CComPtr<IOleClientSite> pClientSite = 0;
CComPtr<IWebBrowser2> m_spBrowser = 0;
CComPtr<IHTMLDocument2> m_spDoc = 0;
CComPtr<IDispatch> pscript;
IUnknown *iUn;
iUn = GetControllingUnknown();
hr = iUn->QueryInterface(IID_IOleObject, reinterpret_cast<void **> (&pOleObject));
if (FAILED(hr))
{
AfxMessageBox("pOleObject");
return "-1";
}
IServiceProvider *isp, *isp2 = NULL;
hr = pOleObject->GetClientSite(&pClientSite);
if (!pClientSite)
{
AfxMessageBox("pClientSite");
return "-1";
}
else
{
try
{
hr = pClientSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **> (&isp));
if (FAILED(hr))
{
AfxMessageBox("IID_IServiceProvider");
return "-1";
}
hr = isp->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, reinterpret_cast<void **>(&isp2));
if (FAILED(hr))
{
AfxMessageBox("SID_STopLevelBrowser");
return "-1";
}
hr = isp2->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, reinterpret_cast<void **>(&m_spBrowser));
if (FAILED(hr))
{
AfxMessageBox("SID_SWebBrowserApp");
return "-1";
}
hr = m_spBrowser->get_Document((IDispatch**)&m_spDoc);
if(FAILED(hr))
{
AfxMessageBox("get_Document");
return "-1";
}
}
catch(LPCTSTR lpszErr)
{
if(CString(lpszErr)!="")
AfxMessageBox(lpszErr);
return "-1";
}
catch(...)
{
AfxMessageBox("未知错误");
return "-1";
}
isp->Release();
isp2->Release();
}
hr = m_spDoc->get_Script(&pscript);
if(FAILED(hr))
{
AfxMessageBox("get_Script");
return "-1";
}
CComBSTR bstrMember("PageInterface");//这里得到页面的方法
DISPID dispid;
hr = pscript->GetIDsOfNames(IID_NULL, &bstrMember, 1, LOCALE_SYSTEM_DEFAULT, &dispid);
if(FAILED(hr))
{
AfxMessageBox("GetIDsOfNames");
return "-1";
}
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = 4;
dispparams.rgvarg = new VARIANT[dispparams.cArgs];
for(int i=0; i<3; i++)
dispparams.rgvarg[i].vt = VT_I4;
dispparams.rgvarg[0].lVal = lParam1;
dispparams.rgvarg[1].lVal = lParam2;
dispparams.rgvarg[2].lVal = lParam3;
dispparams.rgvarg[3].vt = VT_BSTR;
dispparams.rgvarg[i].bstrVal = strParam.AllocSysString();
dispparams.cNamedArgs = 0;
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
_variant_t Var;
Var.Clear();
CComVariant varesult;
UINT nArgErr = (UINT)-1;
hr = pscript->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, &dispparams, &varesult, &excepInfo, &nArgErr);//调用 页面方法
delete []dispparams.rgvarg;
if (FAILED(hr))
{
CString strMSG;
strMSG.Format("调用脚本函数出错[%d]!\n\nlParam1 = %d,lParam2 = %d,lParam3 = %d, strParam = %s", GetLastError(), lParam1, lParam2, lParam3, strParam);
AfxMessageBox(strMSG);
return "-1";
}
else
{
CString Result;
if (varesult.vt != VT_EMPTY)
{
Result = varesult.bstrVal;
}
else
{
Result = "1";
}
return Result;
}
}
上面这个页面的方法要在顶层页面定义
可以用VBScript或者JavaScript实现,在ActiveX中设定一个事件,当ActiveX完成任务后
Fire这个事件,在VBScript中可以刷新页面,差不多就是这样:
<SCRIPT FOR=MyActiveX1 EVENT=ParameterLoaded()>
<!-- {
window.document.write("The parameter you entered is:<br> "
+ MyActiveX1.OutputParameter + " ")
-->
</SCRIPT>
本来事件是比较理想的方法,不过网页中对事件的处理是比较弱的.可以在active中再提供一个接口,在web循环调用,直到这个方法返回值为真时刷新页面