For some time I have been searching for a way to categorize the
properties of my COleControl derived ActiveX control developed in MFC.
As my control has a lot of properties the sort them in categories
would be appreciated a lot by the Visual Basic end-users (I hope,
anyway).
I have seen the ICategorizeProperties approach which works fine for
ATL but I have not been able to make it work in my MFC implementation
and I have not been able to find any examples in MSDN or on the net.
Does anybody know how the ICategorizeProperties interface can be used
from a MFC developed OCX or is there another approach for creating
this interface?
Any reply is appreciated :-)
Regards,
Jacob L.
Well, I worked out the answer to the above. Here is the answer for
anyone who cares:
Add the following to your COleControl derived class CxxxCtrl
(xxxCtrl.h):
/////////////////////////////////////////////////////////////////////////////////////////////////
// Add ICategorizeProperties interface to class
// This interface will allow the properties to categorized into
pre-defined or custom categories.
// The implementation was inspired by MSDN article "Signing and
Marking ActiveX Controls"
// and MSDN technote "TN038: MFC/OLE IUnknown Implementation".
// The ICategorizeProperties interface is described in "Write ActiveX
Controls Using Custom
// Interfaces Provided by ATL 3.0, Part II".
typedef int PROPCAT;
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(CategorizeProperties,IUnknown)
STDMETHOD_(HRESULT,MapPropertyToCategory)(DISPID dispid,PROPCAT
*pPropCat);
STDMETHOD_(HRESULT,GetCategoryName)(PROPCAT PropCat,LCID lcid,BSTR
*pbstrName);
END_INTERFACE_PART(CategorizeProperties);
In the control class implementation (xxxCtrl.cpp file) the following
is added:
/////////////////////////////////////////////////////////////////////////////
// Constants for ICategorizeProperties interface
const IID IID_ICategorizeProperties =
{0x4D07FC10,0xF931,0x11CE,{0xB0,0x01,0x00,0xAA,0x00,0x68,0x84,0xE5}};
// Pre-defined property categories
const int PROPCAT_Nil = -1;
const int PROPCAT_Misc = -2;
const int PROPCAT_Font = -3;
const int PROPCAT_Position = -4;
const int PROPCAT_Appearance= -5;
const int PROPCAT_Behavior = -6;
const int PROPCAT_Data = -7;
const int PROPCAT_List = -8;
const int PROPCAT_Text = -9;
const int PROPCAT_Scale = -10;
const int PROPCAT_DDE = -11;
/////////////////////////////////////////////////////////////////////////////
// Interface map for ICategorizeProperties
BEGIN_INTERFACE_MAP(CIHStreamCtrl,COleControl)
INTERFACE_PART(CIHStreamCtrl,IID_ICategorizeProperties,CategorizeProperties)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// ICategorizeProperties member functions
// Delegate AddRef, Release, QueryInterface
ULONG FAR EXPORT CIHStreamCtrl::XCategorizeProperties::AddRef()
{
METHOD_PROLOGUE(CIHStreamCtrl,CategorizeProperties)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CIHStreamCtrl::XCategorizeProperties::Release()
{
METHOD_PROLOGUE(CIHStreamCtrl,CategorizeProperties)
return pThis->ExternalRelease();
}
HRESULT FAR EXPORT CIHStreamCtrl::XCategorizeProperties::QueryInterface(REFIID
iid,void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CIHStreamCtrl,CategorizeProperties)
return (HRESULT) pThis->ExternalQueryInterface(&iid,ppvObj);
}
// Custom categories (examples)
const int PROPCAT_Cat1 = 1;
const int PROPCAT_Cat2 = 2;
const int PROPCAT_Cat3 = 3;
/*************************/
/* MapPropertyToCategory */
/*************************/
HRESULT STDMETHODCALLTYPE
CIHStreamCtrl::XCategorizeProperties::MapPropertyToCategory(DISPID
dispid,PROPCAT *pPropCat)
{
if (pPropCat == NULL)
return E_POINTER;
switch (dispid)
{
// Category 1 properties
case dispidCat1Property1:
case dispidCat1Property2:
*pPropCat = PROPCAT_Cat;
return S_OK;
// Category 2 properties
case dispidCat2Property1:
*pPropCat = PROPCAT_Cat2;
return S_OK;
// Category 3 properties
case dispidCat3Property1:
case dispidCat3Property2:
case dispidCat3Property3:
*pPropCat = PROPCAT_Cat3;
return S_OK;
}
return E_FAIL;
}
/*******************/
/* GetCategoryName */
/*******************/
HRESULT STDMETHODCALLTYPE
CIHStreamCtrl::XCategorizeProperties::GetCategoryName(PROPCAT PropCat,
LCID lcid,
BSTR *pbstrName)
{
CString strCategory;
switch (PropCat)
{
case PROPCAT_Cat1:
strCategory = "Category 1";
*pbstrName = strCategory.AllocSysString();
return S_OK;
case PROPCAT_Cat2:
strCategory = "Category 2";
*pbstrName = strCategory.AllocSysString();
return S_OK;
case PROPCAT_Cat3:
strCategory = "Category 3";
*pbstrName = strCategory.AllocSysString();
return S_OK;
}
return E_FAIL;
}
And that's it...
Enjoy,
Jacob