65.9K
CodeProject 正在变化。 阅读更多。
Home

通过自定义接口扩展 COM 对象(带运行时属性)

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.80/5 (5投票s)

2003年9月24日

1分钟阅读

viewsIcon

36649

downloadIcon

488

如何通过自定义接口将非 COM 属性传播到 COM 客户端

引言

本文档解释了如何通过不在 IDL 文件中声明的属性来扩展 COM 对象的运行时属性。

这里解释的方法是使用自定义接口 IRtProperties,此方法仅适用于您同时拥有 COM 服务器和 COM 客户端的情况,因为两者都需要知道 IRtProperties 接口的存在。

用法

服务器端

假设您有一个 COM 对象,它将在运行时生成自定义属性,并且您有一个想要识别和管理这些属性的 COM 客户端。

首先,您需要在 COM 对象的头文件中包含头文件 IRtProperties.h
然后,您需要从该接口派生您的对象。

class ATL_NO_VTABLE CSomeCOMObject : 
 public CComObjectRootEx<CComSingleThreadModel>,
 public CComCoClass<CSomeCOMObject , &CLSID_SomeCOMObject >,
 public IRtProperties  // << Add this line
BEGIN_COM_MAP(CMdnBlockCom)
 COM_INTERFACE_ENTRY(ISomeCOMObject )
 COM_INTERFACE_ENTRY(IDispatch)
 COM_INTERFACE_ENTRY(IRtProperties) // << Add this line
END_COM_MAP()

下一步是重写接口的**所有**函数。以下是列表:

// *** IRtProperties ***
    
 STDMETHOD(GetRtPropertiesCount)(THIS_ 
  /* [out] */ LONG* pCount) PURE;

  STDMETHOD(GetRtPropertyName)(THIS_ 
  /* [in]  */ LONG propid,
  /* [out] */ BSTR* pbstrName) PURE;
    
  STDMETHOD(GetRtPropertyCategory)(THIS_
  /* [in]  */ LONG propid,
  /* [out] */ BSTR* pbstrName,
  /* [out] */ PROPCAT* ppropcat) PURE;
 STDMETHOD(GetRtPropertyType)(THIS_
  /* [in]  */ LONG propid,
  /* [out] */ VARTYPE* vt) PURE;
 STDMETHOD(IsRtPropertyEnabled)(THIS_
  /* [in]  */ LONG propid,
  /* [out] */ BOOL* isEnabled) PURE;
 STDMETHOD(SetRtPropertyValue)(THIS_
  /* [in]  */ LONG propid,
  /* [in] */ VARIANT newVal) PURE;
 STDMETHOD(GetRtPropertyValue)(THIS_
  /* [in]  */ LONG propid,
  /* [out] */ VARIANT* pVal) PURE;
 STDMETHOD(GetRtPredefinedStrings)(THIS_
  /* [in]  */ LONG propid,
  /* [out] */ CALPOLESTR *pcaStringsOut,
  /* [out] */ CADWORD *pcaCookiesOut) PURE; 

解释

假设您的运行时属性是按如下方式声明的 PROPERTY 数组:

struct PROPERTY{
       CString name;
       CString value;
}

CArray <PROPERTY,PROPERTY> m_myRtProperties;

GetRtPropertiesCount :返回运行时属性的总数。

示例

STDMETHODIMP CSomeCOMObject ::GetRtPropertiesCount(
 /* [out] */ LONG* pCount)
{
 *pCount = m_myRtProperties.GetSize();
 return S_OK;
}

GetRtPropertyName :按索引返回属性名称。

示例

STDMETHODIMP CMdnBlockCom::GetRtPropertyName(
 /* [in]  */ LONG propid,
    /* [out] */ BSTR* pbstrName)
{

   *pbstrName=::SysAllocString(m_myRtProperties[propid].name);
   return S_OK;
}

继续重写**所有**函数。

客户端

从客户端,当您获取对象的 IDispatch IUnknown 接口时,查询它以获取 IRtProperties 接口。

hr = pUnk->QueryInterface(IID_IRtProperties, (void**)&irtp);
 if (FAILED(hr) || irtp == NULL)
  return;
当您拥有 IRtProperties 接口后,只需使用其函数来操作对象的运行时属性即可。

示例

long propCount;
 irtp->GetRtPropertiesCount(&propCount);
 CComBSTR bstrName, bstrCategory;
 PROPCAT catId;
 for (int i = 0; i < propCount; i++)
 {
  irtp->GetRtPropertyName(i,&bstrName);
  irtp->GetRtPropertyCategory(i,&bstrCategory,&catId);
  VARTYPE vt;
  irtp->GetRtPropertyType(i,&vt);
  if (vt == VT_ARRAY)
  {
   CALPOLESTR     castr; 
   CADWORD        cadw;
   hr = irtp->GetRtPredefinedStrings(i,&castr,&cadw);
   if (hr == S_OK)
   {
    for (ULONG j = 0; j < castr.cElems; j++)
    {
     CString szVal(castr.pElems[j]);
     int index = otiCombo->AddString(szVal);
     otiCombo->CComboBox::SetItemData(j,cadw.pElems[j]);
    }
    CoTaskMemFree((void *)cadw.pElems); 
    CoTaskMemFree((void *)castr.pElems); 
   }
  }

  BOOL bReadOnly;
  irtp->IsRtPropertyEnabled(i,&bReadOnly);

}
if (irtp)
  irtp->Release();
© . All rights reserved.