Click here to Skip to main content
Click here to Skip to main content

Extending COM object with runtime properties through custom interface

, 23 Sep 2003
Rate this:
Please Sign up or sign in to vote.
How to propogate non COM properties to COM client through custom interface
<!-- Article Starts - DO NOT ADD HTML/BODY START TAGS--><!-- Download Links --> <!-- Add the rest of your HTML here -->

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

Share

About the Author

Alex Hazanov
Software Developer (Senior) RDV Systems
Israel Israel
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411022.1 | Last Updated 24 Sep 2003
Article Copyright 2003 by Alex Hazanov
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid