在ATL项目中,实现下面两个方法,可达目的:

   
  STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
  
LCID lcid, DISPID* rgdispid)
{
HRESULT hr = IDispatchImpl<ITestSample, &IID;_ITestSample, &LIBID;_TestCOMLib, 1, 0>::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
if(DISP_E_UNKNOWNNAME == hr) // 若有不存在的成员
{
hr = S_OK;
for(UINT i=0; i<cNames; i++)
if(DISPID_UNKNOWN == rgdispid[i]) // 成员不存在
if(rgszNames[i][0] >= L'A' && rgszNames[i][0] <= L'Z' || rgszNames[i][0] == L'_') // 若首字母是大写或下划线
rgdispid[i] = -999; // 把 DISPID_UNKNOWN 替换为自定义保留值
else
hr = DISP_E_UNKNOWNNAME;
}
return hr;
}

STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{ // 返回值为VT_EMPTY,js中为undefined,标识这是一个不存在的方法
if(-999 == dispidMember) // 若为自定义保留值,即不存在的方法
return 0 - DISP_E_UNKNOWNNAME; // 返回一个正值,使不产生异常
HRESULT hr = IDispatchImpl<ITestSample, &IID;_ITestSample, &LIBID;_TestCOMLib, 1, 0>::Invoke(dispidMember, riid, lcid,
wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
if( SUCCEEDED(hr) && pvarResult && VT_EMPTY == pvarResult->vt )
{
pvarResult->vt = VT_I4; // 成功时,对没有返回值的方法,返回0,表示成功
pvarResult->lVal = 0;
}
if( FAILED(hr) && pvarResult && dispidMember >= 0 )
{
pvarResult->vt = VT_NULL; // 失败时,返回null,表示失败
hr = 0 - hr; // 返回一个正值,使不产生异常
}
return hr;
}

注意:<ITestSample, &IID_ITestSample, &LIBID_TestCOMLib, 1, 0>部分需用实际模板参数替换

为了区分是COM对象的成员,还是HTML OBJECT元素的成员,需要约定:
COM对象的成员以大写字母或下划线打头;
HTML OBJECT元素的成员以小写字母或$打头。

不这样处理,HTML OBJECT元素就添加不了成员。

做人渣真好 answered 12 years, 9 months ago

Your Answer