控件的属性列表则通过控件的TypeInfo接口可以得到,得到Dispatch接口指针后,调用
GetTypeInfoCount,往往返回1,或2,第一个接口就是属性和方法的描述,第2个ITypeInfo
接口可能是事件描述的接口,然后调用GetTypeInfo?(可能是吧)得到ITypeInfo接口,
调用ITypeInfo的函数,然后获得函数的数量,根据每一个函数的描述来判断是属性(还分get和put)
还是方法,然后取得该属性的名称,DISPID(Dispatch ID,或称MemberID)
哎呀呀,给你一段C++的代码你自己看吧
BOOL CPropertyWnd::AddDispatch(IUnknown* pIUnknown)
{
IDispatch *pDispatch;
pIUnknown->QueryInterface(IID_IDispatch, (void **)&pDispatch);
ITypeInfo *pTypeInfo;
if (pDispatch == NULL)
return FALSE;
pDispatch->GetTypeInfo(0, LOCALE_SYSTEM_DEFAULT, &pTypeInfo);
if (pTypeInfo == NULL)
return FALSE;
TYPEATTR* pta;
pTypeInfo->GetTypeAttr(&pta);
if (pta->typekind == TKIND_INTERFACE)
{
// 取得第二个接口
ITypeInfo *pInfoTemp;
HREFTYPE hRef;
HRESULT hr = pTypeInfo->GetRefTypeOfImplType(-1, &hRef);
if (FAILED(hr))
return FALSE;
hr = pTypeInfo->GetRefTypeInfo(hRef, &pInfoTemp);
if (FAILED(hr))
return FALSE;
pTypeInfo->ReleaseTypeAttr(pta);
pTypeInfo = pInfoTemp;
pTypeInfo->GetTypeAttr(&pta);
}
int nItem = m_ListCtrl.GetItemCount();
for (int i = 0
i < pta->cFuncs
i++)
{
FUNCDESC* pfd;
pTypeInfo->GetFuncDesc(i, &pfd);
if (pfd->invkind &
DISPATCH_PROPERTYGET
&&
(pfd->wFuncFlags &
(FUNCFLAG_FRESTRICTED | FUNCFLAG_FHIDDEN)) == 0)
{
switch (pfd->elemdescFunc.tdesc.vt)
{
case VT_USERDEFINED:
case VT_EMPTY:
case VT_NULL:
case VT_I2:
case VT_I4:
case VT_R4:
case VT_R8:
case VT_CY:
case VT_DATE:
case VT_BSTR:
case VT_ERROR:
case VT_BOOL:
case VT_VARIANT:
case VT_DECIMAL:
case VT_I1:
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_INT:
case VT_UINT:
case VT_PTR:
{
ITypeInfo* pUserTypeInfo = NULL;
VARTYPE vt;
vt = pfd->elemdescFunc.tdesc.vt;
if (pfd->elemdescFunc.tdesc.vt == VT_USERDEFINED)
{
HREFTYPE hrt = pfd->elemdescFunc.tdesc.hreftype;
vt = VT_USERDEFINED;
HRESULT hr = E_FAIL;
hr = GetEnumTypeInfo(pTypeInfo, hrt, &pUserTypeInfo);
if(FAILED(hr))
vt = GetUserDefinedType(pTypeInfo, hrt);
}
/* if (pfd->elemdescFunc.tdesc.vt == VT_PTR)
{
HREFTYPE hrt = pfd->elemdescFunc.tdesc.lptdesc->hreftype;
VARTYPE vt = pfd->elemdescFunc.tdesc.lptdesc->vt;
if (SUCCEEDED(pTypeInfo->GetRefTypeInfo(hrt, &pUserTypeInfo)))
{
ITypeLib *pITypeLib;
UINT nIndex = NULL;
if (SUCCEEDED(pUserTypeInfo.p->GetContainingTypeLib(&pITypeLib, &nIndex)))
{
CComBSTR bStr = NULL;
pITypeLib.p->GetDocumentation(nIndex, &bStr, NULL, NULL, NULL);
if (bStr == "IFontDisp")
bStr = "Font";
else if (bStr == "IPictureDisp")
bStr = "Picture";
else
continue;
CComVariant varVal;
CComBSTR bstrVal;
CComBSTR bstrDocString;
CComDispatchDriver dd(pDisp);
dd.GetProperty(pfd->memid, &varVal);
CProperty* pProp = new CProperty(pDisp, pfd->memid, varVal, vt, bstrDocString, spUserTypeInfo);
pProp->GetStringValue(&bstrVal);
m_list.AddItem(nItem, 0, OLE2T(bStr));
m_list.AddItem(nItem, 1, OLE2T(bstrVal));
m_list.SetItemData(nItem, reinterpret_cast<DWORD>(pProp));
nItem++;
}
}
continue;
}
*/
COleVariant varVal;
BSTR bstrVal;
BSTR bstrName;
BSTR bstrDocString;
pTypeInfo->GetDocumentation(pfd->memid, &bstrName, &bstrDocString, NULL, NULL);
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
pDispatch->Invoke(pfd->memid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
&dispparamsNoArgs, &varVal, NULL, NULL);
CProperty* pProp = new CProperty(pDispatch, pfd->memid, varVal, bstrDocString, pUserTypeInfo);
pProp->GetStringValue((BSTR*)&bstrVal);
CString strName = bstrName;
CString strVal = bstrVal;
AddItem(nItem, 0, strName);
AddItem(nItem, 1, strVal);
m_ListCtrl.SetItemData(nItem, reinterpret_cast<DWORD>(pProp));
nItem++;
}
}
}
pTypeInfo->ReleaseFuncDesc(pfd);
}
pTypeInfo->ReleaseTypeAttr(pta);
return S_OK;
}
试试吧!