Article ID: 163244
Article Last Modified on 11/21/2006
m_bCheckCacheForDirtyFields = FALSE;
//****************************************************************
// rfx_double2.cpp
// Most of this code is copied from the MFC source--see comments
// for NEW code.
//
// .cpp file for version of RFX_Double that uses an epsilon value
// in its dirty field comparison.
//
// THIS CODE IS WRITTEN TO WORK WITH MFC 4.2, TO WORK WITH OTHER
// VERSIONS, THIS CODE MAY REQUIRE EXTENSIVE MODIFICATION.
#include "stdafx.h"
// NEW: Constant required for clean compile--different versions of MFC
// use different constants.
static const double afxDoublePseudoNull = AFX_RFX_DOUBLE_PSEUDO_NULL;
// NEW: Comparison that uses an epsilon to define a window within
// which two values are considered equal.
BOOL AFXAPI CompareValueWithEpsilon(void* pvSrc, void* pvDest,
int nSrcType, double epsilon)
{
// Only call with type of double -- you can modify this to accept
// other types.
if (nSrcType != AFX_RFX_DOUBLE)
{
// called with unexpected type
ASSERT(FALSE);
return FALSE;
}
BOOL bDirty = FALSE;
// Do dirty detection comparison factoring in epsilon value.
if ((*(double *)pvDest) > ((*(double *)pvSrc) + epsilon) ||
(*(double *)pvDest) < ((*(double *)pvSrc) - epsilon))
bDirty = TRUE;
return !bDirty;
}
// Fourth parameter is new to this version--it allows you to specify
// the width of the comparison window.
//
// NOTE: Epsilon is expected to be positive.
void AFXAPI RFX_Double2(CFieldExchange* pFX, LPCTSTR szName,
double& value, double epsilon)
{
ASSERT(AfxIsValidAddress(pFX, sizeof(CFieldExchange)));
ASSERT(AfxIsValidString(szName));
switch (pFX->m_nOperation)
{
case CFieldExchange::MarkForUpdate:
{
// NEW: You must move this from original MFC location
// to avoid problems with delegating in default case.
UINT nField;
if (!pFX->IsFieldType(&nField))
return;
if (value != afxDoublePseudoNull)
pFX->m_prs->ClearNullFieldStatus(nField - 1);
// Get the field data,
CFieldInfo* pInfo = &pFX->m_prs->m_rgFieldInfos[nField - 1];
// If the user changed the field value from previous value,
// mark field dirty.
if ((pInfo->m_bStatus & AFX_SQL_FIELD_FLAG_NULL))
{
if (!pFX->m_prs->IsFieldStatusNull(nField - 1))
pFX->m_prs->SetDirtyFieldStatus(nField - 1);
}
else
{
// Saved field is not NULL. The current field is null,
// so the field is dirty.
BOOL bDirty = pFX->m_prs->IsFieldStatusNull(nField - 1);
// If values differ, then field dirty
void* pvDataCache = pInfo->m_pvDataCache;
// NEW: Now call a function that does dirty field
// detection based on an epsilon value.
if (bDirty ||
!CompareValueWithEpsilon(&value, pvDataCache,
pInfo->m_nDataType, epsilon))
pFX->m_prs->SetDirtyFieldStatus(nField - 1);
}
#ifdef _DEBUG
// Field address must not change--ODBC's SQLBindCol depends
// upon this.
void* pvBind = &value;
if (pInfo->m_pvBindAddress != pvBind)
{
TRACE1("Error: field address (column %u) has changed!\n",
nField);
ASSERT(FALSE);
}
#endif // _DEBUG
if ((pFX->m_pvField == NULL || pFX->m_pvField == &value) &&
pFX->m_prs->IsFieldStatusDirty(nField - 1))
{
pFX->m_bField = TRUE;
}
break;
}
// NEW: Only process MarkForUpdate--delegate all else.
default:
{
// NEW: Call the original RFX function for all
// cases but MarkForUpdate.
RFX_Double(pFX,szName, value);
}
return;
}
}
Additional query words: CRecordview DDX_FieldText FPP kbVC151 kbVC152 kbVC200 kbVC210 kbVC220 kbVC 400 kbVC410 kbVC420 kbVC500 kbVC600 s_mfc kbMfc kbtshoot MfcDatabase
Keywords: kbprb KB163244