?? numfrm.cpp
字號:
//_________________________________________________________________
//
// NumFrm.cpp
//
// Written by Eugeny Berezkin,
// E-mail: Eugeny.Berezkin@cma.ru
//_________________________________________________________________
//
#include "stdafx.h"
#include "Afxtempl.h"
#include "NumFrm.h"
#include "colors.h"
#include <math.h>
#ifdef _UNICODE
#include <afxpriv.h> // For A2W & W2A conversions
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Format characters definition
#define FRM_OPEN_BRACKET _T('[')
#define FRM_CLOSE_BRACKET _T(']')
#define FRM_PURGE_SIGN _T('~')
#define FRM_DEC_POINT _T('.')
#define FRM_SECTION_DELIM _T(';')
#define FRM_DIGIT _T('#')
#define FRM_DIGIT_ZERO _T('0')
#define FRM_DIGIT_BALNKS _T('?')
#define FRM_THOUSAND_SEP _T(',')
#define FRM_PERSENT _T('%')
#define OUTCHAR_BLANK _T(' ')
#define INTL_GROUP_DIGIT_LEN 3
#define INTL_NEGATIVE_STR _T("-")
//_________________________________________________________________
//
// CFrmCondition private helper class definition
//
class CFrmCondition
{
public:
CFrmCondition();
CFrmCondition(int nSign, double nLimit);
BOOL Satisfied(double nValue) const;
private:
double m_nLimit;
int m_nSign;
};
typedef CArray<CFrmCondition, CFrmCondition&> CFrmConditionsArray;
//_________________________________________________________________
//
// CNumFrmNode private helper class defenition
//
class CNumFrmNode
{
public:
CNumFrmNode();
LPCTSTR PrintSimpleNumFormat(double nOut, int nForceDec) const;
LPCTSTR PrintNumFormat(double nVal, CDC* pDC, LPRECT lpRect, UINT nFormat, int nForceDec, BOOL bFull) const;
LPCTSTR PrintNumFormatETO(double nVal, CDC* pDC, int x, int y, UINT nOptions, LPCRECT lpRect, int nForceDec, BOOL bFull) const;
BOOL Satisfied(double nValue) const;
BOOL IsConditional() const;
BOOL SetFormat(const CString& sFormat);
void SetCondition(int nSign, double nLimit);
BOOL IsEmpty() const { return m_sFormat.IsEmpty(); };
void Reset();
private:
BOOL GobbleText1(CString& sFrm);
void ProcessPower(LPCTSTR pBuff);
static void ProcessNumFlags(LPCTSTR pBuff, int& nFlags);
BOOL GobbleInt(CString& sFrm);
BOOL ExtractColorOrCondition(CString& sFmt);
BOOL ExtractPercent(CString& sFmt);
BOOL ExtractPurgeSign(CString& sFmt);
BOOL RecognizedAsColor(const CString& sItem);
BOOL RecognizedAsCondition(const CString& sItem);
void BeforePrint(double nVal, CDC* pDC, LPCRECT lpRect, int nForceDec, BOOL bFull) const;
void AfterPrint(CDC* pDC, LPCRECT lpRect) const;
static BOOL WinFormat(LPTSTR szOutput, int nOutBufferLen, double nNumb, int nDec,
BOOL bThousandSepareted, BOOL bIntZeroObligated);
enum EDigitFlags
{
DF_DIGIT = 1,
DF_DIGIT_ZERO = 2,
DF_DIGIT_BALNKS = 4,
DF_THOUSANDS = 8,
};
enum ECommonFlags
{
CF_USE_COLOR = 1,
CF_USE_POWER = 2,
CF_USE_PERCENT = 4,
CF_PURGE_SIGN = 8,
};
CString m_sFormat;
double m_nPowered;
int m_nDec;
int m_nLeftFlags;
int m_nRightFlags;
int m_nCommonFlags;
COLORREF m_Color;
CString m_sText1;
CString m_sText2;
CFrmConditionsArray m_arConditions;
static TCHAR m_pTmpBuffer[MAX_NFORMAT_LEN + 1];
static BOOL m_bLocaleInitialized;
static CString m_sThousand;
static CString m_sDecimal;
};
//_________________________________________________________________
//
TCHAR CNumFrmNode::m_pTmpBuffer[MAX_NFORMAT_LEN + 1];
BOOL CNumFrmNode::m_bLocaleInitialized = FALSE;
CString CNumFrmNode::m_sThousand;
CString CNumFrmNode::m_sDecimal;
//_________________________________________________________________
//
// Enumeration of comparison operations
// and array of corresponding strings
//
enum ESigns
{
SGN_EQUAL,
SGN_NOEQUAL,
SGN_LESS,
SGN_GREATER,
SGN_LESS_OR_EQUAL_1,
SGN_LESS_OR_EQUAL_2,
SGN_GREATER_OR_EQUAL_1,
SGN_GREATER_OR_EQUAL_2,
};
static LPCTSTR szComparisonSigns[] =
{
_T("="),
_T("#"),
_T("<"),
_T(">"),
_T("<="),
_T("=<"),
_T(">="),
_T("=>"),
NULL,
};
//_________________________________________________________________
//
// Helper functions
//
inline static BOOL NonZero(double nValue)
{
const double nMinBound = -1.0e-100;
const double nMaxBound = 1.0e-100;
return nValue > nMaxBound || nValue < nMinBound;
}
static CString Extract(CString& str, int nStart, int nFinish)
{
CString sRet;
if(nStart <= nFinish && nStart < str.GetLength())
{
sRet = str.Mid(nStart, nFinish - nStart + 1);
str = str.Mid(0, nStart) + str.Mid(nFinish + 1);
}
return sRet;
}
static CString GetLine(CString& str, TCHAR pchDelim)
{
CString sRetStr;
int pos;
pos = str.Find(pchDelim);
if(pos != -1)
{
sRetStr = str.Left(pos);
str = str.Mid(pos + 1);
}
else
{
sRetStr = str;
str.Empty();
}
return sRetStr;
}
//_________________________________________________________________
//
// Constructor without initialization
// is used only in CArray::SetSize()
// (CArray::ConstructElements call).
//
CFrmCondition::CFrmCondition()
{
}
CFrmCondition::CFrmCondition(int nSign, double nLimit)
{
m_nSign = nSign;
m_nLimit = nLimit;
}
BOOL CFrmCondition::Satisfied(double nValue) const
{
BOOL bResult;
switch(m_nSign)
{
case SGN_EQUAL:
bResult = !NonZero(m_nLimit - nValue);
break;
case SGN_NOEQUAL:
bResult = NonZero(m_nLimit - nValue);
break;
case SGN_LESS:
bResult = nValue < m_nLimit && NonZero(m_nLimit - nValue);
break;
case SGN_GREATER:
bResult = nValue > m_nLimit && NonZero(m_nLimit - nValue);
break;
case SGN_LESS_OR_EQUAL_1:
case SGN_LESS_OR_EQUAL_2:
bResult = nValue < m_nLimit || !NonZero(m_nLimit - nValue);
break;
case SGN_GREATER_OR_EQUAL_1:
case SGN_GREATER_OR_EQUAL_2:
bResult = nValue > m_nLimit || !NonZero(m_nLimit - nValue);
break;
default:
ASSERT(FALSE);
}
return bResult;
}
//_________________________________________________________________
//
CNumFrmNode::CNumFrmNode()
{
Reset();
}
BOOL CNumFrmNode::SetFormat(const CString& sFormat)
{
if(sFormat != m_sFormat)
{
Reset();
if( sFormat.IsEmpty() )
return TRUE;
if( sFormat.GetLength() > MAX_NFORMAT_LEN )
return FALSE;
CString sFrm = sFormat;
if(!ExtractColorOrCondition(sFrm)) return FALSE;
if(!ExtractPercent(sFrm)) return FALSE;
if(!ExtractPurgeSign(sFrm)) return FALSE;
if(!GobbleText1(sFrm)) return FALSE;
if(!GobbleInt(sFrm)) return FALSE;
m_sText2 = sFrm;
m_sFormat = sFormat;
}
return TRUE;
}
void CNumFrmNode::Reset()
{
m_sFormat.Empty();
m_nPowered = 1.0;
m_nDec = 0;
m_nLeftFlags = 0;
m_nRightFlags = 0;
m_nCommonFlags = 0;
m_Color = Black;
}
BOOL CNumFrmNode::Satisfied(double nValue) const
{
if(m_arConditions.GetSize())
{
for(int i = 0; i < m_arConditions.GetSize(); i++)
{
if(!m_arConditions[i].Satisfied(nValue))
return FALSE;
}
}
return TRUE;
}
void CNumFrmNode::SetCondition(int nSign, double nLimit)
{
CFrmCondition cond(nSign, nLimit);
m_arConditions.Add(cond);
}
BOOL CNumFrmNode::IsConditional() const
{
return m_arConditions.GetSize() ? TRUE : FALSE;
}
BOOL CNumFrmNode::ExtractColorOrCondition(CString& sFmt)
{
int pos_open;
int pos_close;
CString sItem;
while( (pos_open = sFmt.Find(FRM_OPEN_BRACKET)) != -1 &&
(pos_close = sFmt.Find(FRM_CLOSE_BRACKET)) != -1 &&
pos_open < pos_close )
{
sItem = Extract(sFmt, pos_open, pos_close);
if(!RecognizedAsColor(sItem))
RecognizedAsCondition(sItem);
}
return TRUE;
}
BOOL CNumFrmNode::RecognizedAsColor(const CString& sItem)
{
static struct FmtColorMap
{
LPCTSTR pColorName;
COLORREF cColor;
} pColorMap[] =
{
{ _T("[Green]"), Green },
{ _T("[Red]"), Red },
{ _T("[Blue]"), Blue },
{ _T("[Magenta]"), Magenta },
{ _T("[Cyan]"), Cyan },
{ _T("[Yellow]"), Yellow },
{ _T("[White]"), White },
{ _T("[Black]"), Black },
{ NULL , 0 },
};
FmtColorMap* pMap = pColorMap;
while(pMap->pColorName)
{
if(sItem.CompareNoCase(pMap->pColorName) == 0)
{
m_nCommonFlags |= CF_USE_COLOR;
m_Color = pMap->cColor;
return TRUE;
}
pMap++;
}
return FALSE;
}
BOOL CNumFrmNode::RecognizedAsCondition(const CString& sItem)
{
CString sTmp;
CString sSign;
int i;
sTmp = sItem.Mid(1, sItem.GetLength() - 2);
for(i = 0; i < sTmp.GetLength() && !(_istdigit(sTmp[i])) && sTmp[i] != _T('-'); i++)
;
if(i > 0 && i < sTmp.GetLength())
{
sSign = sTmp.Mid(0, i);
sSign.TrimLeft();
sSign.TrimRight();
// look
for(int j = 0; szComparisonSigns[j] != NULL; j++)
{
if(szComparisonSigns[j] == sSign)
{
double nValue;
#ifdef _UNICODE
USES_CONVERSION;
LPCSTR pAStr;
LPCTSTR pWStr = ((LPCTSTR)sTmp) + i;
pAStr = W2CA(pWStr);
nValue = atof(pAStr);
#else
nValue = atof(((LPCTSTR)sTmp) + i);
#endif
CFrmCondition cond(j, nValue);
m_arConditions.Add(cond);
return TRUE;
}
}
}
return FALSE;
}
BOOL CNumFrmNode::ExtractPercent(CString& sFmt)
{
int pos = sFmt.Find(FRM_PERSENT);
if(pos != -1)
{
Extract(sFmt, pos, pos);
m_nCommonFlags |= CF_USE_PERCENT;
m_nPowered = m_nPowered * 100;
}
return TRUE;
}
BOOL CNumFrmNode::ExtractPurgeSign(CString& sFmt)
{
int pos = sFmt.Find(FRM_PURGE_SIGN);
if(pos != -1)
{
Extract(sFmt, pos, pos);
m_nCommonFlags |= CF_PURGE_SIGN;
}
return TRUE;
}
BOOL CNumFrmNode::GobbleText1(CString& sFrm)
{
// Declaration of format string for sscanf
// _T("%[^#0?,.]")
static const TCHAR szSScanfFormat[] =
{ _T('%'), _T('['), _T('^'),
FRM_DIGIT, FRM_DIGIT_ZERO, FRM_DIGIT_BALNKS,
FRM_THOUSAND_SEP, FRM_DEC_POINT,
_T(']'), 0 };
m_pTmpBuffer[0] = 0;
_stscanf(sFrm, szSScanfFormat, m_pTmpBuffer);
m_sText1 = m_pTmpBuffer;
if(m_sText1.GetLength())
sFrm = sFrm.Mid(m_sText1.GetLength());
return TRUE;
}
BOOL CNumFrmNode::GobbleInt(CString& sFrm)
{
// Declaration of format string for sscanf 1
// _T("%[#0?,]")
static const TCHAR szSScanfFormat1[] =
{ _T('%'), _T('['),
FRM_DIGIT, FRM_DIGIT_ZERO, FRM_DIGIT_BALNKS,
FRM_THOUSAND_SEP,
_T(']'), 0 };
// Declaration of format string for sscanf 2
// _T("%[#0?]")
static const TCHAR szSScanfFormat2[] =
{ _T('%'), _T('['),
FRM_DIGIT, FRM_DIGIT_ZERO, FRM_DIGIT_BALNKS,
_T(']'), 0 };
// Declaration of format string for sscanf 3
// _T("%[,]")
static const TCHAR szSScanfFormat3[] =
{ _T('%'), _T('['),
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -