⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplepointcursorhelper.cpp

📁 COM编程接口处理方法 多个方法调用COM库函数
💻 CPP
字号:
// SimplePointCursorHelper.cpp : Implementation of CSimplePointCursorHelper
#include "stdafx.h"
#include "SimplePointVC.h"
#include "SimplePointCursorHelper.h"

/////////////////////////////////////////////////////////////////////////////
// CSimplePointCursorHelper

STDMETHODIMP CSimplePointCursorHelper::InterfaceSupportsErrorInfo(REFIID riid)
{
	static const IID* arr[] = 
	{
		&IID_ISimplePointCursorHelper
	};
	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		if (InlineIsEqualGUID(*arr[i],riid))
			return S_OK;
	}
	return S_FALSE;
}


HRESULT CSimplePointCursorHelper::FinalConstruct()
{
  HRESULT hr;

	m_lCurLineNum = 0;
  m_lOID = -1;

	hr = m_ipWorkPoint.CreateInstance(CLSID_Point);
  if (FAILED(hr)) return hr;

	ISpatialReferencePtr ipSR;
	hr = ipSR.CreateInstance(CLSID_UnknownCoordinateSystem);
  if (FAILED(hr)) return hr;

	hr = m_ipWorkPoint->putref_SpatialReference(ipSR);
  if (FAILED(hr)) return hr;

  return S_OK;
}

void CSimplePointCursorHelper::FinalRelease()
{
	if (m_fDataFile)
		m_fDataFile.close();

	SafeArrayUnaccessData(m_vFieldMap.parray);  
}


// IPlugInCursorHelper
STDMETHODIMP CSimplePointCursorHelper::NextRecord()
{
	HRESULT hr;
	// We will take the line number in the file to be the OID of the feature,
	// keep track of this in the m_lCurLineNum variable.
	// 
  // E_FAIL is returned if there are no more records
	
	// If we are searching by OID, skip to the correct line
  if (m_lOID != -1)
	{
    for ( ; m_lCurLineNum < m_lOID && (!m_fDataFile.eof()); m_lCurLineNum++ )
		{
      m_fDataFile.getline(m_sCurrentRow, c_iMaxRowLen);
		}
		if (m_lCurLineNum != m_lOID) // i.e. EOF before OID found
		{
			 m_sCurrentRow[0] = '\0';
       return E_FAIL;
		}
		else 
			 return S_OK;
	}

  // Read current row
	if (!m_fDataFile.eof())
	{
	  m_fDataFile.getline(m_sCurrentRow, c_iMaxRowLen);
		m_lCurLineNum++;
	}
	else
	{
	  m_sCurrentRow[0] = '\0';
    return E_FAIL;
	}

	// If we are finding by envelope, check the current record
  //   if its not in the envelope, make a recursive call to move on to the next record
  if (m_ipQueryEnv != NULL)
	{
	  hr = QueryShape(m_ipWorkPoint);
		if (FAILED(hr)) return hr;
    
    IRelationalOperatorPtr ipRelOp = m_ipWorkPoint;
		if (ipRelOp == NULL) return E_FAIL;

		VARIANT_BOOL bWithin;
		hr = ipRelOp->Within(m_ipQueryEnv, &bWithin);
		if (FAILED(hr)) return hr;

		if (!bWithin) // current feature is not within the query envelope
		{
      hr = NextRecord();
			if (FAILED(hr)) return hr;
		}
	}

	return S_OK;
}

STDMETHODIMP CSimplePointCursorHelper::IsFinished(VARIANT_BOOL *finished)
{
	if (! finished) return E_POINTER;
	
  *finished = (m_fDataFile.eof()) ? VARIANT_TRUE : VARIANT_FALSE;

	return S_OK;
}

STDMETHODIMP CSimplePointCursorHelper::QueryValues(IRowBuffer *Row, long *OID)
{
	HRESULT hr;
	if (! OID || ! Row) return E_POINTER;
	
  // At end of file, return -1
  if (m_sCurrentRow == '\0')
  {
    *OID = -1;
		return S_OK;
	}

	// First, parse the attribute out of the current row.
  // We know this data source has just one attribute, which is one char wide.
  char sAtt[2];
  strncpy(sAtt, m_sCurrentRow + 12, 1);
	sAtt[1] = '\0'; // add null terminator

	CComVariant vAtt = sAtt;
	if (vAtt.vt == VT_ERROR) return E_FAIL;

	// Check field map has same number of elements as there are fields
	IFieldsPtr ipFields;
	hr = Row->get_Fields(&ipFields);
	if (FAILED(hr)) return hr;

	long lNumFields;
	hr = ipFields->get_FieldCount(&lNumFields);
	if (FAILED(hr)) return hr;

  long lUBound, lLBound;
	hr =  SafeArrayGetLBound(m_vFieldMap.parray, 1, &lLBound);
	if (FAILED(hr)) return hr;
	hr =  SafeArrayGetUBound(m_vFieldMap.parray, 1, &lUBound);
	if (FAILED(hr)) return hr;

  if ( (lUBound - lLBound) + 1   != lNumFields)
  {
  	AtlReportError(CLSID_SimplePointCursorHelper, L"SimplePoint Data Source: Unexepected situation: Number of elements in Fieldmap does not match number of fields", IID_IPlugInCursorHelper, E_FAIL);
    return E_FAIL;
	}

	// For each field, copy its value into the row object.
  // (don't copy shape, object ID or where the field map indicates no values required)
  // Note, although we know there is only one attribute in the data source,
  // this loop has been coded generically in case support needs to be added for more attributes
	long i;
	esriFieldType eFieldType;

	for (i=0; i < lNumFields; i++)
  {
		IFieldPtr ipField;
    hr = ipFields->get_Field(i, &ipField);
		if (FAILED(hr)) return hr;

		hr = ipField->get_Type(&eFieldType);
		if (FAILED(hr)) return hr;

		if (eFieldType     != esriFieldTypeGeometry &&
			  eFieldType     != esriFieldTypeOID &&
				m_lFieldMap[i] != -1)
		{
      hr = Row->put_Value(i, vAtt);
			if (FAILED(hr)) return hr;
		}
	}
	// Return value is taken as the OID.
  // Use the line number (stream will currently be pointing at next line)
	*OID = m_lCurLineNum;
	
	return S_OK;
}

STDMETHODIMP CSimplePointCursorHelper::QueryShape(IGeometry *pGeometry)
{
	HRESULT hr;
	if (! pGeometry) return E_POINTER;

  // If there is no current row, set the geometry to be empty
  if (m_sCurrentRow == '\0')
  {
		hr = pGeometry->SetEmpty();
	  if (FAILED(hr)) return hr;

		return S_OK;
	}

	double x,y;
	char* end;
	char buf[6];

  // Parse the X and Y values out of the current row and into the geometry
	x = strtod(strncpy(buf, m_sCurrentRow, 6),&end);
	y = strtod(strncpy(buf, m_sCurrentRow + 6, 6),&end);

  IPointPtr ipPoint = pGeometry;
	if (ipPoint == NULL) return E_FAIL;

	hr = ipPoint->PutCoords(x,y);
	if (FAILED(hr)) return hr;

  // Note - in our case there is no need to handle the strictSearch test for a cursor
  // created with FetchByEnvelope. We have already tested that the feature is within
  // the envelope on the NextRecord call, so there is no possibility of the test
  // failing here.	

	return S_OK;
}


// IPlugInFastQueryValues
STDMETHODIMP CSimplePointCursorHelper::FastQueryValues(long *Values)
{
	HRESULT hr;
  USES_CONVERSION;
	if (! Values) return E_POINTER;

  // If at end of file, return S_FALSE
  if (m_sCurrentRow == '\0')
		return S_FALSE;

  // define the field value structure and cast the passed array
	struct FieldValue
	{
    VARIANT m_value;
    ULONG m_length;
    DWORD m_status;
	};
	FieldValue* valueArray;
	valueArray = (FieldValue*)Values;

  // First, parse the attribute out of the current row.
  // We know this data source has just one attribute, which is one char wide.
  char sAtt[2];
  strncpy(sAtt, m_sCurrentRow + 12, 1);
	sAtt[1] = '\0'; // add null terminator


  // For this sample, there is just one attribute field to handle,
	// but for demonstration, more generic code follows:
	if (m_ipFields == NULL) return E_FAIL;
  
	IFieldPtr ipField;
	esriFieldType eFieldType;
	long lFieldCount;
	hr = m_ipFields->get_FieldCount(&lFieldCount);
	if (FAILED(hr)) return hr;

	for (long lFieldIndex = 0; lFieldIndex < lFieldCount; lFieldIndex++)
	{
		// if the supplied value in the field map is -1 then this means
		// that we don't have to populate it with data.
		if (m_lFieldMap[lFieldIndex] == -1)
			continue;

		// If the field map indicator is not -1,
		// it is the location in the FieldValue array that we should place our data.
		// For instance field map array is 0,1,2,3,4 with values of 1,0,-1,4,3
		//  the returned field order (that of the valueArray array) would be:
		//            Field1,Field0,Field2=NULL,Field4,Field3
		long lFieldLoc = m_lFieldMap[lFieldIndex];

		hr = m_ipFields->get_Field(lFieldIndex, &ipField);
		if (FAILED(hr)) return hr;

		hr = ipField->get_Type(&eFieldType);
		if (FAILED(hr)) return hr;

    switch (eFieldType)
    {
      case esriFieldTypeSmallInteger:
				valueArray[lFieldLoc].m_value.vt   = VT_I2;
				// following code is commented out - it just indicates the kind
				// of code that would go in if there were lots of different attributes in
				// the data source
        // field value = GetFieldValue(lFieldIndex);
        // valueArray[lngFieldLoc].m_value.iVal = field value;
				break;      
			case esriFieldTypeInteger:
				valueArray[lFieldLoc].m_value.vt   = VT_I4;
        // field value = GetFieldValue(lFieldIndex);
        // valueArray[lngFieldLoc].m_value.lVal = field value;
				break;
      case esriFieldTypeSingle:
				valueArray[lFieldLoc].m_value.vt   = VT_R4;
				// field value = GetFieldValue(lFieldIndex);
        // valueArray[lngFieldLoc].m_value.fltVal = field value;
				break;
			case esriFieldTypeDouble:
				valueArray[lFieldLoc].m_value.vt   = VT_R8;
				// field value = GetFieldValue(lFieldIndex);
        // valueArray[lngFieldLoc].m_value.dblVal = field value;
				break;
			case esriFieldTypeDate:
				valueArray[lFieldLoc].m_value.vt   = VT_DATE;
				// field value = GetFieldValue(lFieldIndex);
        //valueArray[lngFieldLoc].m_value.date = some value;
				break;
			case esriFieldTypeString:
				// if the string already exists then just reallocate it otherwise create
        if (valueArray[lFieldLoc].m_value.bstrVal != NULL)
				{
          INT success = ::SysReAllocString(&(valueArray[lFieldLoc].m_value.bstrVal), A2COLE(sAtt) );
				  if (!success) return E_FAIL;  
        }
        else
				{
          valueArray[lFieldLoc].m_value.bstrVal = ::SysAllocString(A2COLE(sAtt));
					if (valueArray[lFieldLoc].m_value.bstrVal == NULL) return E_FAIL;
        }
				valueArray[lFieldLoc].m_value.vt = VT_BSTR;
				break;
			case esriFieldTypeGeometry:
				// we should never copy the shape field, as QueryShape deals with that
				valueArray[lFieldLoc].m_value.vt = VT_NULL;
				valueArray[lFieldLoc].m_value.punkVal = 0;
				break;
			case esriFieldTypeOID:
				valueArray[lFieldLoc].m_value.vt   = VT_I4;
        valueArray[lFieldLoc].m_value.lVal = m_lCurLineNum;
			case esriFieldTypeBlob:
				break;
			}
	}

	return S_OK;
}


// ISimplePointCursorHelper methods
STDMETHODIMP CSimplePointCursorHelper::put_FilePath(BSTR newVal)
{
	HRESULT hr;
	USES_CONVERSION;

	m_sFilePath = newVal;

	// Open the text file for reading
  m_fDataFile.open(OLE2CA(m_sFilePath));
	if (!m_fDataFile)
	{
		CComBSTR sError(L"Could not open data file for reading: ");
		sError.Append(m_sFilePath);
  	AtlReportError(CLSID_SimplePointCursorHelper, sError, IID_IPlugInCursorHelper, E_FAIL);
		return E_FAIL;
	}

	// First record should be fetched on creation
  hr = NextRecord();
	if (FAILED(hr)) return hr;

	return S_OK;
}

STDMETHODIMP CSimplePointCursorHelper::put_FieldMap(VARIANT fieldMap)
{
	m_vFieldMap = fieldMap;
	
	HRESULT hr = SafeArrayAccessData(m_vFieldMap.parray, (void HUGEP**)&m_lFieldMap);
	if (FAILED(hr)) return hr;

	return S_OK;
}

STDMETHODIMP CSimplePointCursorHelper::put_OID(long lOID)
{
	m_lOID = lOID;
	return S_OK;
}

STDMETHODIMP CSimplePointCursorHelper::putref_QueryEnvelope(IEnvelope* pEnvelope)
{
	m_ipQueryEnv = pEnvelope;
	
	return S_OK;
}

STDMETHODIMP CSimplePointCursorHelper::putref_Fields(IFields* pFields)
{
	// This property exists so we can pass in the fields, to prevent FastQueryValues
	// having to fetch them each time. 
	// We know that the fields will stay constant over the lifetime of the cursor.
	m_ipFields = pFields;
	
	return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -