Click here to Skip to main content
15,882,114 members
Articles / Desktop Programming / MFC

Property list ActiveX control

Rate me:
Please Sign up or sign in to vote.
3.88/5 (23 votes)
4 Nov 20043 min read 190K   7K   58  
Property list similar to VB.NET, implemented as ActiveX control.
// PropListCtl.cpp : Implementation of the CPropListCtrl ActiveX Control class.

#include "stdafx.h"
#include "PropList.h"
#include "PropListCtl.h"
#include "PropListPpg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define BorderNone		0 
#define	BorderRaized	1 
#define	BorderSunken	2
#define	BorderFlat		3
#define	BorderStatic	4

IMPLEMENT_DYNCREATE(CPropListCtrl, COleControl)
CPropListCtrl* pControl = NULL;

/////////////////////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CPropListCtrl, COleControl)
	//{{AFX_MSG_MAP(CPropListCtrl)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_CTLCOLOR()
	//}}AFX_MSG_MAP
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// Dispatch map

BEGIN_DISPATCH_MAP(CPropListCtrl, COleControl)
	//{{AFX_DISPATCH_MAP(CPropListCtrl)
	DISP_PROPERTY_EX(CPropListCtrl, "Precision", GetPrecision, SetPrecision, VT_I2)
	DISP_PROPERTY_EX(CPropListCtrl, "BorderStyle", GetBorderStyle, SetBorderStyle, VT_I2)
	DISP_FUNCTION(CPropListCtrl, "Clear", Clear, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION(CPropListCtrl, "AddProperty", AddProperty, VT_EMPTY, VTS_BSTR VTS_BSTR VTS_VARIANT VTS_BSTR VTS_I2 VTS_BOOL)
	DISP_FUNCTION(CPropListCtrl, "SetValue", SetValue, VT_EMPTY, VTS_BSTR VTS_VARIANT)
	//}}AFX_DISPATCH_MAP
	DISP_FUNCTION_ID(CPropListCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()


/////////////////////////////////////////////////////////////////////////////
// Event map

BEGIN_EVENT_MAP(CPropListCtrl, COleControl)
	//{{AFX_EVENT_MAP(CPropListCtrl)
	EVENT_CUSTOM("PropertyChanged", FirePropertyChanged, VTS_BSTR  VTS_VARIANT)
	EVENT_CUSTOM("ButtonClicked", FireButtonClicked, VTS_BSTR  VTS_I2  VTS_PVARIANT)
	//}}AFX_EVENT_MAP
END_EVENT_MAP()


/////////////////////////////////////////////////////////////////////////////
// Property pages
/*
// TODO: Add more property pages as needed.  Remember to increase the count!
BEGIN_PROPPAGEIDS(CPropListCtrl, 1)
	PROPPAGEID(CPropListPropPage::guid)
END_PROPPAGEIDS(CPropListCtrl)
*/

/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CPropListCtrl, "PROPLIST.PropListCtrl.1",
	0x75c461d9, 0x9588, 0x415a, 0x8d, 0x8f, 0x4e, 0xa2, 0x43, 0x7, 0x3, 0xb9)


/////////////////////////////////////////////////////////////////////////////
// Type library ID and version

IMPLEMENT_OLETYPELIB(CPropListCtrl, _tlid, _wVerMajor, _wVerMinor)


/////////////////////////////////////////////////////////////////////////////
// Interface IDs

const IID BASED_CODE IID_DPropList =
		{ 0x384ef845, 0x4e35, 0x4a9f, { 0xb8, 0x53, 0xc8, 0x98, 0xa5, 0xb5, 0xd, 0x23 } };
const IID BASED_CODE IID_DPropListEvents =
		{ 0x29fd1dc1, 0x292c, 0x4823, { 0x97, 0x51, 0xc5, 0xd1, 0x60, 0xdb, 0xb0, 0x65 } };


/////////////////////////////////////////////////////////////////////////////
// Control type information

static const DWORD BASED_CODE _dwPropListOleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CPropListCtrl, IDS_PROPLIST, _dwPropListOleMisc)


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::CPropListCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CPropListCtrl

BOOL CPropListCtrl::CPropListCtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: Verify that your control follows apartment-model threading rules.
	// Refer to MFC TechNote 64 for more information.
	// If your control does not conform to the apartment-model rules, then
	// you must modify the code below, changing the 6th parameter from
	// afxRegApartmentThreading to 0.

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_PROPLIST,
			IDB_PROPLIST,
			afxRegApartmentThreading,
			_dwPropListOleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}


/////////////////////////////////////////////////////////////////////////////
// Licensing strings

static const TCHAR BASED_CODE _szLicFileName[] = _T("PropList.lic");

static const WCHAR BASED_CODE _szLicString[] =
	L"Copyright (c) 2004 Meidan";


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::CPropListCtrlFactory::VerifyUserLicense -
// Checks for existence of a user license

BOOL CPropListCtrl::CPropListCtrlFactory::VerifyUserLicense()
{
	return 1;
	return AfxVerifyLicFile(AfxGetInstanceHandle(), _szLicFileName,
		_szLicString);
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::CPropListCtrlFactory::GetLicenseKey -
// Returns a runtime licensing key

BOOL CPropListCtrl::CPropListCtrlFactory::GetLicenseKey(DWORD dwReserved,
	BSTR FAR* pbstrKey)
{
	if (pbstrKey == NULL)
		return FALSE;

	*pbstrKey = SysAllocString(_szLicString);
	return (*pbstrKey != NULL);
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::CPropListCtrl - Constructor

CPropListCtrl::CPropListCtrl()
{
	InitializeIIDs(&IID_DPropList, &IID_DPropListEvents);

	// TODO: Initialize your control's instance data here.
	LOGFONT lf;
	memset(&lf, 0, sizeof(LOGFONT));   // Clear out structure.
	lf.lfHeight = 13;                  // Request a 20-pixel-high font
	strcpy(lf.lfFaceName, "Tahoma");    //    with face name "Arial".
	fntReg.CreateFontIndirect(&lf);
	lf.lfWeight = FW_BOLD;
	fntBold.CreateFontIndirect(&lf);
	m_brush.CreateSolidBrush(RGB(255,255,255));
	pControl = this;
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::~CPropListCtrl - Destructor

CPropListCtrl::~CPropListCtrl()
{
	// TODO: Cleanup your control's instance data here.
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::OnDraw - Drawing function

void CPropListCtrl::OnDraw(
			CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
	// TODO: Replace the following code with your own drawing code.
	pdc->FillSolidRect(rcInvalid,RGB(255,255,255));
	CRect rc = rcBounds;
	switch (m_border)
	{
	case BorderRaized:
		pdc->DrawEdge(rc,EDGE_RAISED,BF_RECT);
		break;
	case BorderSunken:
		pdc->DrawEdge(rc,EDGE_SUNKEN,BF_RECT);
		break;
	case BorderFlat:
		pdc->DrawEdge(rc,BDR_RAISEDOUTER|BDR_RAISEDINNER,BF_RECT|BF_FLAT);
		break;
	case BorderStatic:
		pdc->DrawEdge(rc,BDR_SUNKENINNER,BF_RECT);
		break;
	}
	rc.top = rc.bottom-60;
	
	CFont* pOldFont = (CFont*)pdc->SelectObject(&fntBold);
	rc.DeflateRect(2,1);
	pdc->DrawEdge(rc,EDGE_ETCHED,BF_RECT);
	rc.DeflateRect(3,2);
	pdc->DrawText("Description:",rc,DT_SINGLELINE|DT_LEFT|DT_TOP);

	if (IsWindow(m_list.m_hWnd))
	{
		pdc->SaveDC();
		CRect rcList;
		m_list.GetWindowRect(rcList);
		ScreenToClient(&rcList);             // relative to this view
		CPoint ptOffset = rcBounds.TopLeft();
		ptOffset += rcList.TopLeft();
		pdc->LPtoDP(&ptOffset);
        pdc->OffsetViewportOrg(ptOffset.x, ptOffset.y);
		m_list.Print(pdc,PRF_CLIENT);
		pdc->RestoreDC(-1);
	}
//	m_list.PrintClient(pdc,PRF_CLIENT);

	if (!IsOptimizedDraw())
	{
		// The container does not support optimized drawing.

		// TODO: if you selected any GDI objects into the device context *pdc,
		//		restore the previously-selected objects here.
		//		For more information, please see MFC technical note #nnn,
		//		"Optimizing an ActiveX Control".
		if (pOldFont)
			pdc->SelectObject(pOldFont);
	}
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::DoPropExchange - Persistence support

void CPropListCtrl::DoPropExchange(CPropExchange* pPX)
{
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
	COleControl::DoPropExchange(pPX);

	// TODO: Call PX_ functions for each persistent custom property.
	PX_Short(pPX,"BorderStyle",m_border,4);
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::GetControlFlags -
// Flags to customize MFC's implementation of ActiveX controls.
//
// For information on using these flags, please see MFC technical note
// #nnn, "Optimizing an ActiveX Control".
DWORD CPropListCtrl::GetControlFlags()
{
	DWORD dwFlags = COleControl::GetControlFlags();


	// The control can optimize its OnDraw method, by not restoring
	// the original GDI objects in the device context.
	dwFlags |= canOptimizeDraw;
	return dwFlags;
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::OnResetState - Reset control to default state

void CPropListCtrl::OnResetState()
{
	COleControl::OnResetState();  // Resets defaults found in DoPropExchange

	// TODO: Reset any other control state here.
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl::AboutBox - Display an "About" box to the user

void CPropListCtrl::AboutBox()
{
	CDialog dlgAbout(IDD_ABOUTBOX_PROPLIST);
	dlgAbout.DoModal();
}


/////////////////////////////////////////////////////////////////////////////
// CPropListCtrl message handlers

int CPropListCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (COleControl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	CRect rectCl;
	GetClientRect(rectCl);
	rectCl.bottom -= 60;
	m_list.Create(WS_CHILD|WS_VISIBLE|WS_VSCROLL|LBS_HASSTRINGS|LBS_NOTIFY|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWVARIABLE,
			rectCl,this,100);

	m_info.Create ("",WS_CHILD|WS_VISIBLE,rectCl,this);
	m_info.SetFont(&fntReg);
	m_list.info = &m_info;
	return 0;
}

void CPropListCtrl::OnSize(UINT nType, int cx, int cy) 
{
	COleControl::OnSize(nType, cx, cy);
	
	// TODO: Add your message handler code here
	CRect rectCl;
	GetClientRect(rectCl);
	rectCl.DeflateRect(2,2);
	rectCl.bottom -= 60;
	if (IsWindow(m_list.m_hWnd))
		m_list.MoveWindow(rectCl);
	rectCl.top = rectCl.bottom+16;
	rectCl.bottom+=60;
	rectCl.DeflateRect(3,2);
	if (IsWindow(m_info.m_hWnd))
		m_info.MoveWindow(rectCl);
}

void CPropListCtrl::Clear() 
{
	// TODO: Add your dispatch handler code here
	m_list.Clear();
}

short CPropListCtrl::GetPrecision() 
{
	// TODO: Add your property handler here

	return m_precision;
}

void CPropListCtrl::SetPrecision(short nNewValue) 
{
	// TODO: Add your property handler here
	if (nNewValue >= 0 && nNewValue < 10)
		m_precision = nNewValue;
	SetModifiedFlag();
}

void CPropListCtrl::AddProperty(LPCTSTR Category, LPCTSTR Caption, const VARIANT FAR& Value, LPCTSTR Description, short ButtonType, BOOL IsEnabled) 
{
	// TODO: Add your dispatch handler code here
	m_list.AddProperty(Category,Caption,Value,Description,ButtonType,IsEnabled);
}

HBRUSH CPropListCtrl::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	// TODO: Change any attributes of the DC here
	pDC->SetBkColor(RGB(255,255,255));
	
	// TODO: Return a different brush if the default is not desired
		
	return m_brush;
}

void CPropListCtrl::OnPropertyChanged(LPCTSTR PropertyName, const VARIANT &NewValue)
{
	FirePropertyChanged(PropertyName,NewValue);
}

void CPropListCtrl::OnButtonClicked(LPCTSTR PropertyName, short ButtonType, VARIANT *Value)
{
	FireButtonClicked(PropertyName,ButtonType,Value);
}

short CPropListCtrl::GetBorderStyle() 
{
	// TODO: Add your property handler here
	return m_border;
}

void CPropListCtrl::SetBorderStyle(short nNewValue) 
{
	// TODO: Add your property handler here
	m_border = nNewValue;
	SetModifiedFlag();
	Invalidate();
}

void CPropListCtrl::SetValue(LPCTSTR PropertyName, const VARIANT FAR& Value) 
{
	// TODO: Add your dispatch handler code here
	HRESULT res = m_list.SetValue(PropertyName,Value);
	CString str;
	str.Format("Property \"%s\" does not exist",PropertyName);
	if (res == E_FAIL)
		ThrowError(CTL_E_PROPERTYNOTFOUND,str);
	if (res == E_INVALIDARG)
		ThrowError(CTL_E_INVALIDPROPERTYVALUE,"Wrong parameter type");
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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


Written By
Software Developer (Senior) RDV Systems
Israel Israel
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions