Click here to Skip to main content
15,885,914 members
Articles / Desktop Programming / MFC

Using IHTMLEditDesigner

Rate me:
Please Sign up or sign in to vote.
4.88/5 (40 votes)
24 Apr 2004CPOL9 min read 182.4K   3.5K   74  
Using IHTMLEditDesigner to modify IE's editing behaviour
#include "StdAfx.h"
#include ".\variant.h"

//	Constructors
CVariant::CVariant()
{
	vt = VT_EMPTY;
}

CVariant::CVariant(bool bValue)
{
	vt = VT_BOOL;
	boolVal = bValue;
}

CVariant::CVariant(int nValue)
{
	//	Integer overload, set the type and assign the value
	vt = VT_I4;
	intVal = nValue;
}

CVariant::CVariant(LPCTSTR szValue)
{
	//	String overload
	USES_CONVERSION;

	//	Validate the input string
	ASSERT(szValue);
	ASSERT(AfxIsValidString(szValue));

	//	Set the type and allocate a BSTR
	vt = VT_BSTR;
	bstrVal = SysAllocString(A2W(szValue));
}

CVariant::CVariant(VARIANT *pV)
{
	//	Validate the input (and make sure it's writeable)
	ASSERT(pV);
	ASSERT(AfxIsValidAddress(pV, sizeof(VARIANT), TRUE));

	vt = VT_VARIANT;
	pvarVal = pV;
}

CVariant::CVariant(int lBound, int iElementCount)
{
	//	Set the type to an array of variants...
	vt = VT_ARRAY | VT_VARIANT;
	parray = new SAFEARRAY;

	//	We only support 1 dimensional arrays..
	parray->cDims = 1;
	parray->fFeatures = FADF_VARIANT | FADF_HAVEVARTYPE | FADF_FIXEDSIZE | FADF_STATIC;
	parray->cbElements = sizeof(VARIANT);
	parray->cLocks = 0;

	//	Allocate the array of variants we point to...
	parray->pvData = new VARIANT[iElementCount];
	memset(parray->pvData, 0, sizeof(VARIANT) * iElementCount);
	parray->rgsabound[0].lLbound = lBound;
	parray->rgsabound[0].cElements = iElementCount;
}

//	Destructor
CVariant::~CVariant(void)
{
	unsigned long i;

	switch (vt)
	{
	case VT_BSTR:
		SysFreeString(bstrVal);
		break;

	case VT_ARRAY | VT_VARIANT:
		for (i = 0; i < parray->rgsabound[0].cElements; i++)
			if (((VARIANT *) parray->pvData)[i].vt == VT_BSTR)
				SysFreeString(((VARIANT *) parray->pvData)[i].bstrVal);

		delete parray->pvData;
		delete parray;
		break;

	case VT_VARIANT:
		//	We do nothing in this case because it's a
		//	wrapped VARIANT pointer we know little about.
		//	We certainly don't have enough information to
		//	safely delete it so we let it's originator 
		//	worry about it
		break;
	}
}

//	Attributes
BOOL CVariant::IsArray(int iElement)
{
	VARIANT *pV = ElementAt(iElement);
	VARTYPE v;

	if (pV != (VARIANT *) NULL)
	{
		//	One level of indirection
		if (pV->vt == VT_VARIANT && pV->pvarVal != (VARIANT *) NULL)
			v = pV->pvarVal->vt;
		else
			v = pV->vt;

		return v & VT_ARRAY;
	}

	return FALSE;
}

BOOL CVariant::IsInt(int iElement)
{
	VARIANT *pV = ElementAt(iElement);
	VARTYPE v;

	if (pV != (VARIANT *) NULL)
	{
		//	One level of indirection
		if (pV->vt == VT_VARIANT && pV->pvarVal != (VARIANT *) NULL)
			v = pV->pvarVal->vt;
		else
			v = pV->vt;

		switch (v)
		{
		case VT_I1:
		case VT_I2:
		case VT_I4:
			return TRUE;

		default:
			return FALSE;
		}
	}

	return FALSE;
}

//	Private helper function
BOOL CVariant::SingleTypeCheck(VARTYPE vType, int iElement)
{
	VARIANT *pV = ElementAt(iElement);
	VARTYPE v;

	if (pV != (VARIANT *) NULL)
	{
		//	One level of indirection
		if (pV->vt == VT_VARIANT && pV->pvarVal != (VARIANT *) NULL)
			v = pV->pvarVal->vt;
		else
			v = pV->vt;

		return v == vType;
	}

	return FALSE;
}

//	Array operations
VARIANT	*CVariant::ElementAt(int iElement)
{
	if (vt == VT_VARIANT)
		//	It's a pointer to an external VARIANT
		//	so return that variant
		return pvarVal;

	if (!(vt & VT_ARRAY))
		//	It's not an array so return ourselves
		return this;

	//	Calculate our element offset
	int	offset = iElement - parray->rgsabound[0].lLbound;

	//	Offset must be zero or greater and less than the bounds
	if (offset >= 0 && offset <= int(parray->rgsabound[0].cElements))
		return &((VARIANT *) parray->pvData)[offset];
	else
		return (VARIANT *) NULL;
}

CString CVariant::ToString(int iElement)
{
	USES_CONVERSION;

	//	Get the VARIANT at the iElement offset
	VARIANT *v = ElementAt(iElement);

	//	Must be a valid pointer and must be valid readable memory
	if (v != (VARIANT *) NULL && AfxIsValidAddress(v, sizeof(VARIANT), FALSE) && v->vt == VT_BSTR)
		return W2A(v->bstrVal);

	return _T("");
}

int CVariant::ToInt(int iElement)
{
	//	Get the VARIANT at the iElement offset
	VARIANT *v = ElementAt(iElement);

	if (v != (VARIANT *) NULL)
	{
		//	Make sure it's valid readable memory
		if (AfxIsValidAddress(v, sizeof(VARIANT), FALSE))
		{
			//	Now switch on the type to ensure we return
			//	a valid value.
			switch (v->vt)
			{
			case VT_I1:
				return (int) v->bVal;

			case VT_I2:
				return (int) v->iVal;

			case VT_I4:
				return v->lVal;
			}
		}
	}

	return 0;
}

BOOL CVariant::ToBool(int iElement)
{
	VARIANT *v = ElementAt(iElement);

	if (v->vt == VT_BOOL)
		return v->boolVal;
	else
		return FALSE;
}

void CVariant::Set(LPCTSTR szString, int iElement)
{
	USES_CONVERSION;

	ASSERT(szString);
	ASSERT(AfxIsValidString(szString));

	//	Get the VARIANT at the iElement offset
	VARIANT *v = ElementAt(iElement);

	//	Make sure it's valid writeable memory
	if (v != (VARIANT *) NULL && AfxIsValidAddress(v, sizeof(VARIANT), TRUE))
	{
		v->vt = VT_BSTR;
		v->bstrVal = SysAllocString(A2W(szString));
	}
}

void CVariant::Set(int iValue, int iElement)
{
	VARIANT *v = ElementAt(iElement);

	//	Make sure it's valid readable memory
	if (v != (VARIANT *) NULL && AfxIsValidAddress(v, sizeof(VARIANT), TRUE))
	{
		v->vt = VT_I4;
		v->lVal = iValue;
	}
}

void CVariant::Set(bool bValue, int iElement)
{
	VARIANT *v = ElementAt(iElement);

	//	Make sure it's valid readable memory
	if (v != (VARIANT *) NULL && AfxIsValidAddress(v, sizeof(VARIANT), TRUE))
	{
		v->vt = VT_BOOL;
		v->lVal = bValue;
	}
}

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)


Written By
United States United States
I've been programming for 35 years - started in machine language on the National Semiconductor SC/MP chip, moved via the 8080 to the Z80 - graduated through HP Rocky Mountain Basic and HPL - then to C and C++ and now C#.

I used (30 or so years ago when I worked for Hewlett Packard) to repair HP Oscilloscopes and Spectrum Analysers - for a while there I was the one repairing DC to daylight SpecAns in the Asia Pacific area.

Afterward I was the fourth team member added to the Australia Post EPOS project at Unisys Australia. We grew to become an A$400 million project. I wrote a few device drivers for the project under Microsoft OS/2 v 1.3 - did hardware qualification and was part of the rollout team dealing directly with the customer.

Born and bred in Melbourne Australia, now living in Scottsdale Arizona USA, became a US Citizen on September 29th, 2006.

I work for a medical insurance broker, learning how to create ASP.NET websites in VB.Net and C#. It's all good.

Oh, I'm also a Kentucky Colonel. http://www.kycolonels.org

Comments and Discussions