373 lines
10 KiB
C++
373 lines
10 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXPhysicalEdit
|
|
// ==========================================================================
|
|
|
|
// Source file : OXPhysicalEdit.cpp
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "StdAfx.h" // standard MFC include
|
|
#include "OXPhysicalEdit.h"
|
|
#include "UTB64Bit.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
IMPLEMENT_DYNAMIC(COXPhysicalEdit, COXNumericEdit)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Definition of static members
|
|
// Data members -------------------------------------------------------------
|
|
// protected:
|
|
// int m_nUnitIndex;
|
|
// --- The last used unit (during SetValue or construction) of this edit control
|
|
|
|
// COXConversionData* m_pConversionData;
|
|
// --- Pointer to the conversion data or NULL
|
|
|
|
// private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
// public:
|
|
|
|
BEGIN_MESSAGE_MAP(COXPhysicalEdit, COXNumericEdit)
|
|
//{{AFX_MSG_MAP(COXPhysicalEdit)
|
|
//}}AFX_MSG_MAP
|
|
ON_COMMAND_RANGE(ID_OXPHYSICALEDIT_INDEXBASE,0xffff,OnChangeUnit)
|
|
END_MESSAGE_MAP()
|
|
|
|
COXPhysicalEdit::COXPhysicalEdit()
|
|
:
|
|
m_nUnitIndex(-1),
|
|
m_pConversionData(NULL),
|
|
m_bShowUnit(FALSE)
|
|
{
|
|
}
|
|
|
|
COXPhysicalEdit::COXPhysicalEdit(COXConversionData* pConversionData,
|
|
int nDefaultUnitIndex /* = -1 */,
|
|
BOOL bShowUnit/*=TRUE*/)
|
|
:
|
|
m_nUnitIndex(nDefaultUnitIndex),
|
|
m_pConversionData(pConversionData),
|
|
m_bShowUnit(FALSE)
|
|
{
|
|
if (nDefaultUnitIndex == -1)
|
|
{
|
|
// No default unit was specified, than valid conversion data must be supplied,
|
|
// so we can extract a default unit from that data
|
|
ASSERT(pConversionData != NULL);
|
|
ASSERT(AfxIsValidAddress(pConversionData, sizeof(COXConversionData)));
|
|
m_nUnitIndex = pConversionData->m_nDefaultUnitIndex;
|
|
}
|
|
|
|
if(pConversionData!=NULL)
|
|
{
|
|
VERIFY(m_menu.CreatePopupMenu());
|
|
LPCTSTR* arrUnitNames=GetUnitNames();
|
|
for(int nIndex=0; nIndex<GetNumberOfUnits(); nIndex++)
|
|
{
|
|
m_menu.AppendMenu(MF_STRING,nIndex+ID_OXPHYSICALEDIT_INDEXBASE,
|
|
arrUnitNames[nIndex]);
|
|
}
|
|
AssociateMenu(&m_menu);
|
|
}
|
|
|
|
ShowUnit(bShowUnit);
|
|
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
void COXPhysicalEdit::SetValue(double dValue, int nUnit /* = -1 */,
|
|
LPCTSTR pszFormat /* = NULL */)
|
|
{
|
|
ASSERT_VALID(this);
|
|
// ASSERT((pszFormat == NULL) || AfxIsValidString(pszFormat));
|
|
UNREFERENCED_PARAMETER(pszFormat);
|
|
|
|
// ... Check for default unit
|
|
if (nUnit==-1)
|
|
nUnit=GetDefaultUnit();
|
|
if(m_nUnitIndex!=nUnit)
|
|
m_nUnitIndex=nUnit;
|
|
|
|
COXNumericEdit::SetValue(dValue);
|
|
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
double COXPhysicalEdit::GetValue(int nUnit /* = -1 */, BOOL bNotify /* = TRUE */)
|
|
{
|
|
UNREFERENCED_PARAMETER(bNotify);
|
|
|
|
ASSERT_VALID(this);
|
|
|
|
double dValue=COXNumericEdit::GetValue();
|
|
if(nUnit!=m_nUnitIndex)
|
|
{
|
|
if(nUnit==-1)
|
|
{
|
|
nUnit=GetDefaultUnit();
|
|
}
|
|
dValue=Convert(dValue,m_nUnitIndex,nUnit);
|
|
}
|
|
|
|
ASSERT_VALID(this);
|
|
return dValue;
|
|
}
|
|
|
|
void COXPhysicalEdit::UpdateMask()
|
|
{
|
|
COXNumericEdit::UpdateMask();
|
|
if(GetShowUnit())
|
|
{
|
|
m_bShowUnit=FALSE;
|
|
ShowUnit(TRUE);
|
|
}
|
|
}
|
|
|
|
void COXPhysicalEdit::ShowUnit(BOOL bShowUnit)
|
|
{
|
|
if(bShowUnit!=m_bShowUnit)
|
|
{
|
|
ASSERT(m_nUnitIndex!=-1);
|
|
CString sUnitName(_T(" "));
|
|
sUnitName+=GetUnitNames()[m_nUnitIndex];
|
|
|
|
CString sMask=GetMask();
|
|
int nPosInputData=sMask.Find(OXEDITABLETEXT_SYMBOL);
|
|
CString sRightLiterals=(nPosInputData==-1 ? _T("") : sMask.Mid(nPosInputData+1));
|
|
|
|
int nOffset=PtrToInt(m_arrRightLiterals.GetSize()-sRightLiterals.GetLength());
|
|
ASSERT(nOffset>=0);
|
|
for(int nIndex=0; nIndex<sUnitName.GetLength(); nIndex++)
|
|
{
|
|
if(bShowUnit)
|
|
{
|
|
m_arrRightLiterals.InsertAt(nIndex+nOffset,sUnitName[nIndex]);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_arrRightLiterals.GetSize()>0);
|
|
m_arrRightLiterals.RemoveAt(nOffset-sUnitName.GetLength());
|
|
}
|
|
}
|
|
|
|
m_bShowUnit=bShowUnit;
|
|
|
|
Update(-1);
|
|
}
|
|
}
|
|
|
|
double COXPhysicalEdit::Convert(double dValue, int nUnitFrom, int nUnitTo)
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// MAke a call to the static version
|
|
return ConversionHelper(dValue, nUnitFrom, nUnitTo, GetConversionParams());
|
|
}
|
|
|
|
double COXPhysicalEdit::ConversionHelper(double dValue, int nUnitFrom, int nUnitTo, COXConversionParams* pConversionParams)
|
|
{
|
|
ASSERT(pConversionParams != NULL);
|
|
ASSERT(AfxIsValidAddress(pConversionParams, sizeof(COXConversionParams)));
|
|
|
|
// ... Convert value to default unit
|
|
double dDefValue = (dValue + pConversionParams[nUnitFrom].m_dPreTerm) *
|
|
pConversionParams[nUnitFrom].m_dFactor + pConversionParams[nUnitFrom].m_dPostTerm;
|
|
// ... and then to requested unit
|
|
ASSERT(pConversionParams[nUnitTo].m_dFactor != 0);
|
|
double dRequestValue = (dDefValue - pConversionParams[nUnitTo].m_dPostTerm) /
|
|
pConversionParams[nUnitTo].m_dFactor - pConversionParams[nUnitTo].m_dPreTerm;
|
|
return dRequestValue;
|
|
}
|
|
|
|
int COXPhysicalEdit::GetNumberOfUnits()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// If this function is called, m_pConversionData should point to valid data
|
|
// If you do not want to use m_pConversionData, you should override this function
|
|
// in a derived class
|
|
ASSERT(m_pConversionData != NULL);
|
|
|
|
return m_pConversionData->m_nNumberOfUnits;
|
|
}
|
|
|
|
int COXPhysicalEdit::GetDefaultUnit()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// If this function is called, m_pConversionData should point to valid data
|
|
// If you do not want to use m_pConversionData, you should override this function
|
|
// in a derived class
|
|
ASSERT(m_pConversionData != NULL);
|
|
|
|
return m_pConversionData->m_nDefaultUnitIndex;
|
|
}
|
|
|
|
LPCTSTR* COXPhysicalEdit::GetUnitNames()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// If this function is called, m_pConversionData should point to valid data
|
|
// If you do not want to use m_pConversionData, you should override this function
|
|
// in a derived class
|
|
ASSERT(m_pConversionData != NULL);
|
|
|
|
return m_pConversionData->m_ppszUnitNames;
|
|
}
|
|
|
|
COXConversionParams* COXPhysicalEdit::GetConversionParams()
|
|
{
|
|
ASSERT_VALID(this);
|
|
|
|
// If this function is called, m_pConversionData should point to valid data
|
|
// If you do not want to use m_pConversionData, you should override this function
|
|
// in a derived class
|
|
ASSERT(m_pConversionData != NULL);
|
|
|
|
return m_pConversionData->m_pConversionParams;
|
|
}
|
|
|
|
void COXPhysicalEdit::ShowErrorMessage(LPCTSTR pszUnit)
|
|
{
|
|
SetFocus();
|
|
CString sMessage;
|
|
CString sFullMessage;
|
|
|
|
// If this function is called, m_pConversionData should point to valid data
|
|
// If you do not want to use m_pConversionData, you should override this function
|
|
// in a derived class
|
|
ASSERT(m_pConversionData != NULL);
|
|
|
|
if ((m_pConversionData != NULL) && (m_pConversionData->m_pszErrorMsg != NULL))
|
|
{
|
|
if (HIWORD(m_pConversionData->m_pszErrorMsg) == NULL)
|
|
{
|
|
// Implicit resource ID specified, load it
|
|
UINT nID = LOWORD((DWORD_PTR)m_pConversionData->m_pszErrorMsg);
|
|
sMessage.LoadString(LOWORD((DWORD)nID));
|
|
}
|
|
else
|
|
// Explicit string pointer
|
|
sMessage = m_pConversionData->m_pszErrorMsg;
|
|
}
|
|
// ... Fill in the value if the string contains "%1"
|
|
AfxFormatStrings(sFullMessage, (LPCTSTR)sMessage, &pszUnit, 1);
|
|
|
|
// Show a message box to the user
|
|
AfxMessageBox(sFullMessage, MB_ICONEXCLAMATION | MB_OK);
|
|
}
|
|
|
|
|
|
void COXPhysicalEdit::OnChangeUnit(UINT nID)
|
|
{
|
|
if((int)nID<ID_OXPHYSICALEDIT_INDEXBASE ||
|
|
(int)nID>=ID_OXPHYSICALEDIT_INDEXBASE+GetNumberOfUnits())
|
|
{
|
|
// don't handle it
|
|
return;
|
|
}
|
|
|
|
nID-=ID_OXPHYSICALEDIT_INDEXBASE;
|
|
SetValue(GetValue(nID),nID);
|
|
UpdateInsertionPointForward(0);
|
|
}
|
|
|
|
|
|
#ifdef _DEBUG
|
|
void COXPhysicalEdit::AssertValid() const
|
|
{
|
|
CEdit::AssertValid();
|
|
CString sDummy;
|
|
|
|
// ... A valid unit index has to be specified !
|
|
ASSERT(0 <= m_nUnitIndex);
|
|
|
|
// If conversion data is supplied, check that it is valid
|
|
if(m_pConversionData != NULL)
|
|
{
|
|
ASSERT(AfxIsValidAddress(m_pConversionData, sizeof(COXConversionData)));
|
|
// ... Should have at least one unit
|
|
ASSERT(0 < m_pConversionData->m_nNumberOfUnits);
|
|
// ... Default unit index has to be valid
|
|
ASSERT(0 <= m_pConversionData->m_nDefaultUnitIndex);
|
|
if(m_pConversionData->m_pszErrorMsg != NULL)
|
|
{
|
|
if (HIWORD(m_pConversionData->m_pszErrorMsg)!=NULL)
|
|
{
|
|
// Explicit string pointer
|
|
ASSERT(AfxIsValidString(m_pConversionData->m_pszErrorMsg));
|
|
}
|
|
}
|
|
|
|
// Array should be valid
|
|
ASSERT(AfxIsValidAddress(
|
|
m_pConversionData->m_ppszUnitNames,
|
|
sizeof(LPCTSTR*) * m_pConversionData->m_nNumberOfUnits));
|
|
ASSERT(AfxIsValidAddress(
|
|
m_pConversionData->m_pConversionParams,
|
|
sizeof(COXConversionParams*) * m_pConversionData->m_nNumberOfUnits));
|
|
for(int nUnitIndex = 0;
|
|
nUnitIndex < m_pConversionData->m_nNumberOfUnits; nUnitIndex++)
|
|
{
|
|
ASSERT(AfxIsValidString(m_pConversionData->m_ppszUnitNames[nUnitIndex]));
|
|
ASSERT(AfxIsValidAddress(
|
|
&m_pConversionData->m_pConversionParams[nUnitIndex],
|
|
sizeof(COXConversionParams)));
|
|
// ... Multiplication factor should never be 0
|
|
ASSERT(m_pConversionData->m_pConversionParams[nUnitIndex].m_dFactor != 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void COXPhysicalEdit::Dump(CDumpContext& dc) const
|
|
{
|
|
COXNumericEdit::Dump(dc);
|
|
}
|
|
#endif //_DEBUG
|
|
|
|
COXPhysicalEdit::~COXPhysicalEdit()
|
|
{
|
|
ASSERT_VALID(this);
|
|
}
|
|
|
|
// protected:
|
|
// private:
|
|
|
|
// global:
|
|
void AFXAPI DDX_OXPhysicalEdit(CDataExchange* pDX, int nIDC, double& dValue, int nUnits)
|
|
{
|
|
// be sure that the control is a COXTimeEdit
|
|
COXPhysicalEdit* pEdit = (COXPhysicalEdit*)pDX->m_pDlgWnd->GetDlgItem(nIDC);
|
|
ASSERT(pEdit->IsKindOf(RUNTIME_CLASS(COXPhysicalEdit)));
|
|
ASSERT_VALID(pEdit);
|
|
if (pDX->m_bSaveAndValidate)
|
|
{
|
|
// retreive data
|
|
dValue = pEdit->GetValue(nUnits);
|
|
}
|
|
else
|
|
{
|
|
// set data
|
|
pEdit->SetValue(dValue, nUnits);
|
|
}
|
|
}
|
|
|
|
// ==========================================================================
|
|
|