Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Extending COM object with runtime properties through custom interface

0.00/5 (No votes)
23 Sep 2003 2  
How to propogate non COM properties to COM client through custom interface

Introduction

This article explains how to extend COM object properties at run time with properties that are not declared in IDL file.

The method explained here is to use custom interface IRtProperties, this method is only aplicable if you are the owner of both the COM server and the COM client since both need to know of existance of the IRtProperties interface.

Usage

Server side

Suppose you have some COM object that will generate custom properties at runtime and you have a COM client that you want to recognize those properties and manage them.

First you have to include the header file IRtProperties.h in your COM object's header.
Than you have to derrive your object from this interface:

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()

Next step is to override all of the interface's functions. Here is the list:

// *** 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; 

Explanation

Suppose your runtime properies is an array of PROPERTY declared as follows:

struct PROPERTY{
       CString name;
       CString value;
}

CArray <PROPERTY,PROPERTY> m_myRtProperties;

GetRtPropertiesCount : returns the total count of runtime properties.

Example

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

GetRtPropertyName : returns property name by index.

Example

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

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

Continue to override all of the functions.

Client side

From the client side when you aquire the IDispatch or IUnknown interface of the object quiry it for the IRtProperies inteface:

hr = pUnk->QueryInterface(IID_IRtProperties, (void**)&irtp);
 if (FAILED(hr) || irtp == NULL)
  return;
When you have the IRtProperties interface just use its functions to manipulate the object's runtime properties.

Example

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();

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here