Click here to Skip to main content
14,038,009 members
Click here to Skip to main content

Stats

298.2K views
79K downloads
226 bookmarked
Posted 30 Dec 2005
Licenced CPOL

Form Designer

, 1 Aug 2009
Component for adding scriptable forms capabilities to an application.
MFCDemo.exe
CSDemo
App.ico
Bmp
ABottom.bmp
About.bmp
ALeft.bmp
ARight.bmp
ATop.bmp
AX.bmp
BringFront.bmp
Button.bmp
Center.bmp
Check.bmp
Combo.bmp
Copy.bmp
Cut.bmp
Delete.bmp
Down.bmp
Edit.bmp
Frame.bmp
Grid.bmp
GridSettings.bmp
HCenter.bmp
HScroll.bmp
HSL.bmp
HSpace.bmp
HSS.bmp
Left.bmp
List.bmp
New.bmp
Open.bmp
Paste.bmp
Picture.bmp
Preview.bmp
Progress.bmp
Props.bmp
Radio.bmp
Rectangle.bmp
Redo.bmp
Right.bmp
Save.bmp
SelAll.bmp
SelNone.bmp
SendBack.bmp
SL.bmp
Slider.bmp
Spin.bmp
SS.bmp
Tab.bmp
Text.bmp
Undo.bmp
Up.bmp
Validate.bmp
VCenter.bmp
VScroll.bmp
VSL.bmp
VSpace.bmp
VSS.bmp
Wand.bmp
CSDemo.suo
DaeDoe.bmp
MFCDemo
MFCDemo.dsp
MFCDemo.odl
MFCDemo.reg
res
DaeDoe.bmp
MFCDemo.ico
MFCDemoDoc.ico
Toolbar1.bmp
Toolbar2.bmp
Toolbar3.bmp
Wand.bmp
VBDemo
Bmp
ABottom.bmp
About.bmp
ALeft.bmp
ARight.bmp
ATop.bmp
AX.bmp
BringFront.bmp
Button.bmp
Center.bmp
Check.bmp
Combo.bmp
Copy.bmp
Cut.bmp
Delete.bmp
Down.bmp
Edit.bmp
Frame.bmp
Grid.bmp
GridSettings.bmp
HCenter.bmp
HScroll.bmp
HSL.bmp
HSpace.bmp
HSS.bmp
Left.bmp
List.bmp
New.bmp
Open.bmp
Paste.bmp
Picture.bmp
Preview.bmp
Progress.bmp
Props.bmp
Radio.bmp
Rectangle.bmp
Redo.bmp
Right.bmp
Save.bmp
SelAll.bmp
SelNone.bmp
SendBack.bmp
SL.bmp
Slider.bmp
Spin.bmp
SS.bmp
Tab.bmp
Text.bmp
Undo.bmp
Up.bmp
Validate.bmp
VCenter.bmp
VScroll.bmp
VSL.bmp
VSpace.bmp
VSS.bmp
Wand.bmp
DaeDoe.bmp
VBDemo.vbp
DDForms.chm
DDForms
Archive
FormEditorItems.rgs
vssver.scc
Constants.scr
DaeDoe.bmp
DDForms.def
DDForms.vcproj
DDForms.vcproj.vspscc
EventSinkPassThrough.rgs
FormEditor.bmp
FormEditor.rgs
FormEditorItemCollection.rgs
FormEditorItemDetails.rgs
FormViewer.bmp
FormViewer.rgs
FormViewerItemCollection.rgs
FormViewerItemDetails.rgs
mssccprj.scc
PropPageExtended.rgs
PropPageFormEditor.rgs
PropPageFormViewer.rgs
PropPageSimpleScriptEditor.rgs
SimpleScriptEditor.bmp
SimpleScriptEditor.rgs
vssver.scc
DDFormsTools
CodeMaxDriver
CodeMaxDriver.rgs
CodeMaxDriver.vcproj
CodeMaxDriver.vcproj.vspscc
CodeMaxDriverps.def
CodeMaxDriverPS.vcproj
CodeMaxDriverPS.vcproj.vspscc
mssccprj.scc
vssver.scc
CodeSenseDriver
CodeSenseDriver.rgs
CodeSenseDriver.vcproj
CodeSenseDriver.vcproj.vspscc
CodeSenseDriverps.def
CodeSenseDriverPS.vcproj
CodeSenseDriverPS.vcproj.vspscc
mssccprj.scc
vssver.scc
DDPropPageAll
DDPropPageAll.def
DDPropPageAll.vcproj
DDPropPageAll.vcproj.vspscc
mssccprj.scc
PropPageAll.rgs
vssver.scc
DDUnlock
DDUnlock.vcproj
DDUnlock.vcproj.vspscc
mssccprj.scc
vssver.scc
DDControlPack
DDButton.bmp
DDCheckBox.bmp
DDComboBox.bmp
DDControlPack.rgs
DDControlPack.vcproj
DDControlPack.vcproj.vspscc
DDHorzScrollBar.bmp
DDLabel.bmp
DDListBox.bmp
DDPicture.bmp
DDRadioButton.bmp
DDTextBox.bmp
DDVertScrollBar.bmp
mssccprj.scc
vssver.scc
Redistributables
Ansi
CodeMaxDriver.dll
CodeSenseDriver.dll
DDControlPack.dll
DDForms.dll
DDPropPageAll.dll
Unicode
CodeMaxDriver.dll
CodeSenseDriver.dll
DDControlPack.dll
DDForms.dll
DDPropPageAll.dll
// PropertyInfo.cpp: implementation of the CPropertyInfo class.
//
// Author : David Shepherd
//			Copyright (c) 2002, DaeDoe-Software
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PropertyInfo.h"

/////////////////////////////////////////////////////////////////////////////
// CPredefinedValue

CPredefinedValue::CPredefinedValue()
{
	// initialise everything
}

CPredefinedValue::~CPredefinedValue()
{
	// clean up
}

/////////////////////////////////////////////////////////////////////////////
// CPropertyInfo

CPropertyInfo::CPropertyInfo()
{
	// initialise everything
	m_DispatchId=DISPID_UNKNOWN;
	m_VariantType=VT_EMPTY;
	m_Type=TypeUnknown;
}

CPropertyInfo::~CPropertyInfo()
{
	// clean up
}

void CPropertyInfo::GetDispatchType(const CComPtr<ITypeInfo> &spTypeInfo)
{
	// get type attributes
	CAutoTypeAttrPtr pTypeAttr(spTypeInfo);
	// check for the font dispatch interface
	if(pTypeAttr->guid==IID_IFontDisp)
	{
		m_VariantType=VT_DISPATCH;
		m_Type=TypeFont;
	}
	// check for the picture dispatch interface
	if(pTypeAttr->guid==IID_IPictureDisp)
	{
		m_VariantType=VT_DISPATCH;
		m_Type=TypePicture;
	}
}

void CPropertyInfo::GetUserDefinedType(
	const CComPtr<ITypeInfo> &spTypeInfo,const TYPEDESC &TypeDesc)
{
	// get type info
	CComPtr<ITypeInfo> spTypeInfoUser;
	if(!SUCCEEDED(spTypeInfo->GetRefTypeInfo(TypeDesc.hreftype,&spTypeInfoUser)))
	{
		throw std::exception();
	}
	// get type attributes
	CAutoTypeAttrPtr pTypeAttrUser(spTypeInfoUser);
	// determine the user defined property type
	switch(pTypeAttrUser->typekind)
	{
	// alias
	case TKIND_ALIAS:
		// check for the color alias
		if(pTypeAttrUser->guid==GUID_COLOR)
		{
			m_VariantType=VT_I4;
			m_Type=TypeColor;
		}
		else	// some other alias
		{
			GetType(spTypeInfoUser,pTypeAttrUser->tdescAlias);
		}
		break;
	// enumerator
	case TKIND_ENUM:
		// set the enumerator predefined values
		SetPredefinedValuesOnEnum(spTypeInfoUser);
		m_VariantType=VT_I4;
		m_Type=TypeEnum;
		break;
	// dispatch interface
	case TKIND_DISPATCH:
		// determine the dispatch interface type
		GetDispatchType(spTypeInfoUser);
		break;
	// other
	default:
		// this is ok
		break;
	}
}

void CPropertyInfo::GetType(
	const CComPtr<ITypeInfo> &spTypeInfo,const TYPEDESC &TypeDesc)
{
	// determine the property type
	m_VariantType=TypeDesc.vt;
	switch(m_VariantType)
	{
	// simple type
	case VT_I2:
	case VT_I4:
	case VT_R4:
	case VT_R8:
	case VT_CY:
	case VT_DATE:
	case VT_BSTR:
	case VT_ERROR:
	case VT_I1:
	case VT_UI1:
	case VT_UI2:
	case VT_UI4:
	case VT_I8:
	case VT_UI8:
	case VT_INT:
	case VT_UINT:
		// all simple types can be represented as a string
		m_Type=TypeString;
		break;
	// boolean type
	case VT_BOOL:
		// set the boolean predefined values
		SetPredefinedValuesOnBool();
		m_Type=TypeBool;
		break;
	// pointer type
	case VT_PTR:
		// determine the type pointed to
		GetType(spTypeInfo,*TypeDesc.lptdesc);
		break;
	// user defined type
	case VT_USERDEFINED:
		// determine the user defined type
		GetUserDefinedType(spTypeInfo,TypeDesc);
		break;
	// variant type
	case VT_VARIANT:
		// force this type to a string
		m_VariantType=VT_BSTR;
		m_Type=TypeString;
		break;
	// dispatch type
	case VT_DISPATCH:
		// determine the dispatch interface type
		GetDispatchType(spTypeInfo);
		break;
	// other type
	default:
		// this is ok
		break;
	}
}

void CPropertyInfo::GetPredefinedValues(const CComPtr<IDispatch> &spDispatch)
{
	// allows type independant auto release of CoTaskMem
	typedef CAutoCoTaskMem<void> CAutoCoFree;

	// get the IPerPropertyBrowsing interface
	CComQIPtr<IPerPropertyBrowsing> spPerPropertyBrowsing(spDispatch);
	if(spPerPropertyBrowsing==NULL)
	{
		return;	// per property browsing is not available
	}
	// retreive predefined values
	CALPOLESTR StringArray	= { 0,NULL };
	CADWORD CookieArray		= { 0,NULL };
	if(!SUCCEEDED(spPerPropertyBrowsing->GetPredefinedStrings(
		m_DispatchId,&StringArray,&CookieArray)))
	{
		return;	// per property browsing is not available
	}
	ATLASSERT(StringArray.cElems==CookieArray.cElems);
	DWORD Count=StringArray.cElems;
	// auto release the string array
	CAutoCoFree pStringElements(StringArray.pElems);
	// auto release the cookie array
	CAutoCoFree pCookieElements(CookieArray.pElems);
	// auto release each string
	// todo : if possible prevent CoTaskMem leaks if new throws
	auto_array_ptr<CAutoCoFree> pStrings(new CAutoCoFree[Count]);
	for(long l=0; l<(long)Count; l++)
	{
		pStrings.get()[l]=CAutoCoFree(StringArray.pElems[l]);
	}
	// add all predefined values to the vector
	if(Count)
	{
		// remove lower priority values
		m_PredefinedValues.clear();
	}
	for(l=0; l<(long)Count; l++)
	{
		// create the predefined value
		CPredefinedValue PredefinedValue;
		// name
		PredefinedValue.m_Name=StringArray.pElems[l];
		// value
		if(!SUCCEEDED(spPerPropertyBrowsing->GetPredefinedValue(
			m_DispatchId,CookieArray.pElems[l],&PredefinedValue.m_Value)))
		{
			throw std::exception();
		}
		// update the vector
		m_PredefinedValues.push_back(PredefinedValue);
	}
}

void CPropertyInfo::SetPredefinedValuesOnBool()
{
	// the vector should be empty
	ATLASSERT(m_PredefinedValues.empty());

	// create the true value
	CPredefinedValue PredefinedValue;
	PredefinedValue.m_Name=L"True";
	PredefinedValue.m_Value=VARIANT_TRUE;
	// ensure the variant type is VT_BOOL
	if(!SUCCEEDED(PredefinedValue.m_Value.ChangeType(VT_BOOL)))
	{
		throw std::exception();
	}
	// update the vector
	m_PredefinedValues.push_back(PredefinedValue);
	// create the false value
	PredefinedValue.m_Name=L"False";
	PredefinedValue.m_Value=VARIANT_FALSE;
	// ensure the variant type is VT_BOOL
	if(!SUCCEEDED(PredefinedValue.m_Value.ChangeType(VT_BOOL)))
	{
		throw std::exception();
	}
	// update the vector
	m_PredefinedValues.push_back(PredefinedValue);
}

void CPropertyInfo::SetPredefinedValuesOnEnum(
	const CComPtr<ITypeInfo> &spTypeInfo)
{
	// the vector should be empty
	ATLASSERT(m_PredefinedValues.empty());

	// get type attributes
	CAutoTypeAttrPtr pTypeAttr(spTypeInfo);
	// add all enumerator values to the vector
	for(long l=0; l<pTypeAttr->cVars; l++)
	{
		// get the variable description
		CAutoVarDescPtr pVarDesc(l,spTypeInfo);
		// create the predefined value
		CPredefinedValue PredefinedValue;
		// name prefix
		CComVariant Value=*pVarDesc->lpvarValue;
		if(!SUCCEEDED(Value.ChangeType(VT_BSTR)))
		{
			throw std::exception();
		}
		std::wstring NamePrefix=BSTR2W(Value.bstrVal);
		NamePrefix+=L" - ";
		// name
		UINT Count=0;
		CComBSTR Name;
		if(!SUCCEEDED(spTypeInfo->GetNames(pVarDesc->memid,&Name,1,&Count)))
		{
			throw std::exception();
		}
		PredefinedValue.m_Name=NamePrefix+BSTR2W(Name);	// include the prefix
		// value
		PredefinedValue.m_Value=*pVarDesc->lpvarValue;
		// update the vector
		m_PredefinedValues.push_back(PredefinedValue);
	}
}

void CPropertyInfo::Create(const CComPtr<IDispatch> &spDispatch,DISPID DispatchId,
	const TYPEDESC &TypeDesc)
{
	// object reuse is not allowed
	ATLASSERT(m_VariantType==VT_EMPTY);

	// get type info
	CComPtr<ITypeInfo> spTypeInfo;
	if(!SUCCEEDED(spDispatch->GetTypeInfo(0,LOCALE_USER_DEFAULT,&spTypeInfo)))
	{
		throw std::exception();
	}
	// create property info
	// name
	UINT Count=0;
	CComBSTR Name;
	if(!SUCCEEDED(spTypeInfo->GetNames(DispatchId,&Name,1,&Count)))
	{
		throw std::exception();
	}
	m_Name=BSTR2W(Name);
	// dispatch id
	m_DispatchId=DispatchId;
	// type
	GetType(spTypeInfo,TypeDesc);
	// predefined values
	GetPredefinedValues(spDispatch);
	// value
	if(m_Type!=TypeUnknown and m_Type!=TypeInvalid)
	{
		GetValue(spDispatch);
	}
}

void CPropertyInfo::GetValue(const CComPtr<IDispatch> &spDispatch)
{
	// the property type should have been determined
	ATLASSERT(m_Type!=TypeUnknown and m_Type!=TypeInvalid);

	// retreive the property value
	CComVariant Value;
	CComDispatchDriver DispatchDriver(spDispatch);
	if(!SUCCEEDED(DispatchDriver.GetProperty(m_DispatchId,&Value)))
	{
		// this may fail for valid reasons so clear the current value
		if(!SUCCEEDED(m_Value.Clear()))
		{
			// unexpected
			ATLASSERT(FALSE);
		}
		return;
	}
	// change the value to the correct type
	if(!SUCCEEDED(Value.ChangeType(m_VariantType)))
	{
		// this may fail for valid reasons so clear the current value
		if(!SUCCEEDED(m_Value.Clear()))
		{
			// unexpected
			ATLASSERT(FALSE);
		}
		return;
	}
	m_Value=Value;	// releases the old value if required
}

std::wstring CPropertyInfo::GetValueName() const
{
	// the value should be set
	ATLASSERT(m_Value.vt!=VT_EMPTY);

	// return the property value name
	std::wstring Name;
	for(long l=0; l<(long)m_PredefinedValues.size() and Name.empty(); l++)
	{
		CPredefinedValue PredefinedValue=m_PredefinedValues[l];
		// match the predefined value type to the property value type
		if(!SUCCEEDED(PredefinedValue.m_Value.ChangeType(m_Value.vt)))
		{
			throw std::exception();
		}
		// compare values
		if(PredefinedValue.m_Value==m_Value)
		{
			Name=PredefinedValue.m_Name;
		}
	}
	return Name;
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

DaveShep
Web Developer
United Kingdom United Kingdom
No Biography provided

You may also be interested in...

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web04 | 2.8.190425.1 | Last Updated 1 Aug 2009
Article Copyright 2005 by DaveShep
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid