// Digistring.cpp : implementation file // // Copyright (C) 2000 by Michel Wassink // All rights reserved // // This is free software. // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name and all copyright // notices remains intact. If the source code in this file is used in // any commercial application then a statement along the lines of // "Portions Copyright © 2000 Michel Wassink" must be included in // the startup banner, "About" box or printed documentation. An email // letting me know that you are using it would be nice as well. That's // not much to ask considering the amount of work that went into this. // // No warrantee of any kind, expressed or implied, is included with this // software; use at your own risk, responsibility for damages (if any) to // anyone resulting from the use of this software rests entirely with the // user. // // Send bug reports, bug fixes, enhancements, requests, flames, etc., and // I'll try to keep a version up to date. I can be reached as follows: // mwassink@csi.com (private site) // An email letting me know that you are using it would be nice. ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Digistring.h" #include "Curvefit.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // Segment numbering: // ----- 13 ----- 0 //|\ | /| 8 0 12 | | 1 2 //| \|/ | 1 2 | | // -- -- == 6 7 ----- == 3 //| /|\ | 3 4 | | //|/ | \| 9 5 11 | | 4 5 // ----- 10 ----- 6 #define MAXSEGCHAR7 12 // Number of supported 7 segment characters #define MAXSEGCHAR14 40 // Number of supported 14 segment characters #define MAXSEGSEMCOL 2 // Number of supported 3 segment characters #define NORM_DIGIHEIGHT 83 // All characters must have this height //////////////////////////////////////////////////////////////////////////////// // For 14 segments display... // SP 0 1 2 3 4 5 6 WORD CHAR_SEGM14[MAXSEGCHAR14] = {0x0000, 0x3F00, 0x1800, 0x36C0, 0x3CC0, 0x19C0, 0x2DC0, 0x2FC0, // 7 8 9 - A B C D E F G H 0x3800, 0x3FC0, 0x3DC0, 0x00C0, 0x3BC0, 0x3CA1, 0x2700, 0x3C21, 0x27C0, 0x23C0, 0x2F80, 0x1BC0, // I J K L M N O P Q R S 0x2421, 0x1E00, 0x0354, 0x0700, 0x1B06, 0x1B12, 0x3F00, 0x33C0, 0x3F10, 0x33D0, 0x2DC0, // T U V W X Y Z * + 0x2021, 0x1F00, 0x030C, 0x1B18, 0x001E, 0x11E0, 0x240C, 0x00FF, 0x00E1}; // straight style CPoint PtSeg14N0[5] = {CPoint(20,13), CPoint(20,36), CPoint(24,40), CPoint(28,36), CPoint(28,13)}; CPoint PtSeg14N1[4] = {CPoint( 5, 5), CPoint(15,35), CPoint(20,37), CPoint(18,25)}; CPoint PtSeg14N6[6] = {CPoint( 6,41), CPoint(14,45), CPoint(18,45), CPoint(22,41), CPoint(18,37), CPoint(14,37)}; CPoint PtSeg14N8[4] = {CPoint( 4, 7), CPoint( 4,40), CPoint(11,36), CPoint(11,26)}; CPoint PtSeg14N13[4] = {CPoint( 6, 4), CPoint(11,11), CPoint(37,11), CPoint(42, 4)}; BYTE TpSeg14N0[5] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSeg14N1[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSeg14N6[6] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSeg14N8[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSeg14N13[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; // smooth style PT_BEZIERTO CPoint PtSeg14N0S[13] ={CPoint(20,12), CPoint(20,25), CPoint(22,36), CPoint(23,39), CPoint(24,40), CPoint(25,39), CPoint(26,36), CPoint(28,25), CPoint(28,12), CPoint(26,10), CPoint(24, 9), CPoint(22,10), CPoint(20,12)}; CPoint PtSeg14N1S[10] ={CPoint(10,10), CPoint(10,13), CPoint(11,20), CPoint(13,28), CPoint(21,38), CPoint(21,37), CPoint(19,26), CPoint(15,16), CPoint(11,10), CPoint(10,10)}; CPoint PtSeg14N6S[6] = {CPoint( 8,41), CPoint(12,45), CPoint(16,45), CPoint(23,41), CPoint(16,37), CPoint(12,37)}; CPoint PtSeg14N8S[10]= {CPoint( 4, 7), CPoint( 4,39), CPoint( 5,40), CPoint( 6,40), CPoint( 9,37), CPoint(11,33), CPoint(11,25), CPoint( 9,14), CPoint( 5, 6), CPoint( 4, 7)}; CPoint PtSeg14N13S[17]={CPoint( 8, 4), CPoint( 7, 5), CPoint( 7, 6), CPoint( 9, 8), CPoint(12, 9), CPoint(14,11), CPoint(19,11), CPoint(21, 9), CPoint(24, 7), CPoint(27, 9), CPoint(29,11), CPoint(34,11), CPoint(36, 9), CPoint(39, 8), CPoint(41, 6), CPoint(41, 5), CPoint(40, 4)}; BYTE TpSeg14N0S[13]= {PT_MOVETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO}; BYTE TpSeg14N1S[10] ={PT_MOVETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO}; BYTE TpSeg14N6S[6] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSeg14N8S[10] ={PT_MOVETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO}; BYTE TpSeg14N13S[17]={PT_MOVETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO}; /////////////////////////////////////////////////////////////////////////////// // For 7 segments display... // SP 0 1 2 3 4 5 BYTE CHAR_SEGM7[MAXSEGCHAR7] = {0x00, 0x77, 0x24, 0x5D, 0x6D, 0x2E, 0x6B, // 6 7 8 9 - 0x7B, 0x25, 0x7F, 0x6F, 0x08}; // straight style CPoint PtSeg7N0[4] = {CPoint( 5, 4), CPoint(12,11), CPoint(36,11), CPoint(43, 4)}; CPoint PtSeg7N1[4] = {CPoint( 4, 6), CPoint( 4,40), CPoint(11,36), CPoint(11,13)}; CPoint PtSeg7N3[6] = {CPoint( 6,41), CPoint(14,45), CPoint(34,45), CPoint(42,41), CPoint(34,37), CPoint(14,37)}; // 3 BYTE TpSeg7N0[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSeg7N1[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSeg7N3[6] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO}; // smooth style PT_BEZIERTO CPoint PtSeg7N0S[7] = {CPoint( 6, 4), CPoint( 5, 5), CPoint( 5, 6), CPoint( 8, 9), CPoint(12,11), CPoint(36,11), CPoint(39, 4)}; CPoint PtSeg7N1S[7] = {CPoint( 4, 9), CPoint( 4,39), CPoint( 6,40), CPoint( 7,40), CPoint( 9,38), CPoint(11,36), CPoint(11,12)}; CPoint PtSeg7N2S[10] = {CPoint(37,36), CPoint(39,38), CPoint(41,40), CPoint(42,40), CPoint(44,39), CPoint(44, 6), CPoint(42, 4), CPoint(41, 4), CPoint(39, 8), CPoint(37,12)}; CPoint PtSeg7N3S[6] = {CPoint( 8,41), CPoint(12,45), CPoint(36,45), CPoint(40,41), CPoint(36,37), CPoint(12,37)}; BYTE TpSeg7N0S[7] = {PT_MOVETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSeg7N1S[7] = {PT_MOVETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_LINETO}; BYTE TpSeg7N2S[10] = {PT_MOVETO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO, PT_LINETO, PT_LINETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO, PT_LINETO}; BYTE TpSeg7N3S[6] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO, PT_LINETO}; // For 3 segments semicoloncombi display... // . : BYTE CHAR_SEMCOL[MAXSEGSEMCOL] = {0x04, 0x03}; CPoint PtSegScN0[4] = {CPoint( 4,23), CPoint( 4,32), CPoint(13,32), CPoint(13,23)}; CPoint PtSegScN1[4] = {CPoint( 4,50), CPoint( 4,59), CPoint(13,59), CPoint(13,50)}; CPoint PtSegScN2[4] = {CPoint( 4,68), CPoint( 4,77), CPoint(13,77), CPoint(13,68)}; BYTE TpSegScN0[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSegScN1[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; BYTE TpSegScN2[4] = {PT_MOVETO, PT_LINETO, PT_LINETO, PT_LINETO}; // Functions for mirroring points... CPoint PointMirror(const CPoint &P, const CPoint &M) { return CPoint(P.x + 2*(M.x - P.x), P.y + 2*(M.y - P.y)); } CPoint LineMirrorX(const CPoint &P, int X) { return CPoint(P.x + 2*(X - P.x), P.y); } CPoint LineMirrorY(const CPoint &P, int Y) { return CPoint(P.x, P.y + 2*(Y - P.y)); } ///////////////////////////////////////////////////////////////////////////// // CDSegment CDSegment::CDSegment() { m_paPoints = NULL; m_paTypes = NULL; } CDSegment::CDSegment(const CDSegment& Segment) { ASSERT(Segment.m_paPoints != NULL); // Do not copy an unitialized segment m_nCount = Segment.m_nCount; m_paPoints = new CPoint[m_nCount]; m_paTypes = new BYTE[m_nCount]; if (m_paPoints != NULL && m_paTypes != NULL) { memcpy(m_paPoints, Segment.m_paPoints, m_nCount * sizeof(CPoint)); memcpy(m_paTypes, Segment.m_paTypes, m_nCount * sizeof(BYTE)); } } // ----------------------------------------------------------------------------- CDSegment::~CDSegment() { FreeSegment(); } void CDSegment::DefPoints(const POINT* lpaPoints, const BYTE* lpaTypes, int nCount) { FreeSegment(); m_paPoints = new CPoint[nCount]; m_paTypes = new BYTE[nCount]; m_nCount = nCount; if (m_paPoints != NULL && m_paTypes != NULL) { memcpy(m_paPoints, lpaPoints, m_nCount * sizeof(CPoint)); memcpy(m_paTypes, lpaTypes, m_nCount * sizeof(BYTE)); } } // ----------------------------------------------------------------------------- CDSegment CDSegment::operator=(const CDSegment &Segment) { CPoint *pNewPoints; BYTE * pNewTypes; m_nCount = Segment.m_nCount; pNewPoints = new CPoint[m_nCount]; pNewTypes = new BYTE[m_nCount]; memcpy(pNewPoints, Segment.m_paPoints, m_nCount * sizeof(CPoint)); memcpy(pNewTypes, Segment.m_paTypes, m_nCount * sizeof(BYTE)); FreeSegment(); // Get rid of old stuff m_paPoints = pNewPoints; m_paTypes = pNewTypes; return *this; } void CDSegment::FreeSegment() { if (m_paPoints != NULL && m_paTypes != NULL) { delete[] m_paPoints; delete[] m_paTypes; m_paPoints = NULL; m_paTypes = NULL; } } void CDSegment::Draw(CDC *pDC, CDoubleRect DrawPlace, int iWidth) const { int i, nBez,b; CPoint * paPoints; double daContr[4]; double *pBezPts; double dRelWidth, dRelHeight; paPoints = new CPoint[m_nCount]; if (paPoints == NULL) return; dRelWidth = DrawPlace.Width() / iWidth; dRelHeight = DrawPlace.Height() / NORM_DIGIHEIGHT; for (i = 0; i < m_nCount; i++) { if (m_paTypes[i] != PT_BEZIERTO) { paPoints[i] = CPoint(DrawPlace.left + dRelWidth * m_paPoints[i].x + 0.5, DrawPlace.top + dRelHeight * m_paPoints[i].y + 0.5); } } for (i = 0; i < m_nCount; i++) { if (m_paTypes[i] == PT_MOVETO) { pDC->MoveTo(paPoints[i]); } else if (m_paTypes[i] == PT_LINETO) { VERIFY(pDC->LineTo(paPoints[i])); } else if (m_paTypes[i] == PT_BEZIERTO) { // Look for the first non-bezier point(This is the EndPoint)... nBez = 0; do { nBez++; } while (m_paTypes[i+nBez] == PT_BEZIERTO); pBezPts = new double[2*(nBez+2)]; for (b = 0; b < (nBez+2)*2; b += 2) { pBezPts[b ] = DrawPlace.left + dRelWidth * m_paPoints[i-1+b/2].x; pBezPts[b+1] = DrawPlace.top + dRelHeight * m_paPoints[i-1+b/2].y; } CalcBezier(pBezPts, 2*(nBez+2), daContr); delete[] pBezPts; paPoints[i ].x = daContr[0] + 0.5; paPoints[i ].y = daContr[1] + 0.5; paPoints[i+1].x = daContr[2] + 0.5; paPoints[i+1].y = daContr[3] + 0.5; paPoints[i+2] = paPoints[i+nBez]; VERIFY(pDC->PolyBezierTo(&paPoints[i], 3)); i += nBez; } } // for delete[] paPoints; } ///////////////////////////////////////////////////////////////////////////// // CDigiChar CDigiChar::CDigiChar() { m_Width = 49; m_wSegmData = 0x0000; // All segments in offcolor } CDigiChar::~CDigiChar() { } void CDigiChar::Draw(CDC *pDC, CDoubleRect DrawPlace, CPen *pOffPen, CPen *pOnPen, CBrush *pOffBrush, CBrush *pOnBrush) { WORD SegMask; DSegmentVector::iterator SegmIterator; SegMask = 1; for (SegmIterator = m_SegmentVector.begin(); SegmIterator != m_SegmentVector.end(); SegmIterator++) { if (m_wSegmData & SegMask) { pDC->SelectObject(pOnBrush); pDC->SelectObject(pOnPen); } else { pDC->SelectObject(pOffBrush); pDC->SelectObject(pOffPen); } pDC->BeginPath(); SegmIterator->Draw(pDC, DrawPlace, m_Width); pDC->EndPath(); pDC->StrokeAndFillPath(); SegMask <<= 1; } } void CDigiChar::SetElementData(WORD wSegmData, int /*iDispStyle*/) { m_wSegmData = wSegmData; } int CDigiChar::GetNormWidth() const { return m_Width; } ///////////////////////////////////////////////////////////////////////////// // CDigi7Segment CDigi7Segment::CDigi7Segment() { m_Width = 49; m_NSegments = 7; } void CDigi7Segment::SetElementData(WORD wSegmData, int iDispStyle) { int i, p; CDSegment TmpSegm; LPPOINT lpTmpSegPoints = NULL; LPPOINT lpSegPoints; LPBYTE lpType; int nCount; m_SegmentVector.clear(); for (i = 0; i < m_NSegments; i++) { switch(i) { case 0: case 6: if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg7N0S; lpType = TpSeg7N0S; nCount = 7; } else { lpSegPoints = PtSeg7N0; lpType = TpSeg7N0; nCount = 4; } break; case 1: case 4:if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg7N1S; lpType = TpSeg7N1S; nCount = 7; } else { lpSegPoints = PtSeg7N1; lpType = TpSeg7N1; nCount = 4; } break; case 2: case 5: if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg7N2S; lpType = TpSeg7N2S; nCount = 10; } else { lpSegPoints = PtSeg7N1; lpType = TpSeg7N1; nCount = 4; } break; case 3: if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg7N3S; lpType = TpSeg7N3S; nCount = 6; } else { lpSegPoints = PtSeg7N3; lpType = TpSeg7N3; nCount = 6; } break; } switch(i) { case 6: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorY(lpSegPoints[p], 41);break; case 2: if (!(iDispStyle & CDigistring::DS_SMOOTH)) { lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorX(lpSegPoints[p], (m_Width-1)/2); } break; case 4: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorY(lpSegPoints[p], 41);break; case 5: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) if (iDispStyle & CDigistring::DS_SMOOTH) lpTmpSegPoints[p] = LineMirrorY(lpSegPoints[p], 41); else lpTmpSegPoints[p] = PointMirror(lpSegPoints[p], CPoint((m_Width-1)/2, 41)); break; } if (lpTmpSegPoints == NULL) TmpSegm.DefPoints(lpSegPoints, lpType, nCount); else { TmpSegm.DefPoints(lpTmpSegPoints, lpType, nCount); delete[] lpTmpSegPoints; lpTmpSegPoints = NULL; } m_SegmentVector.push_back(TmpSegm); } m_wSegmData = wSegmData; } ///////////////////////////////////////////////////////////////////////////// // CDigi14Segment CDigi14Segment::CDigi14Segment() { m_Width = 49; m_NSegments = 14; } void CDigi14Segment::SetElementData(WORD wSegmData, int iDispStyle) { int i, p; CDSegment x; LPPOINT lpTmpSegPoints = NULL; LPPOINT lpSegPoints; LPBYTE lpType; int nCount; m_SegmentVector.clear(); for (i = 0; i < m_NSegments; i++) { switch(i) { case 0: case 5: if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg14N0S; lpType = TpSeg14N0S; nCount = 13; } else { lpSegPoints = PtSeg14N0; lpType = TpSeg14N0; nCount = 5; } break; case 1: case 2: case 3: case 4: if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg14N1S; lpType = TpSeg14N1S; nCount = 10; } else { lpSegPoints = PtSeg14N1; lpType = TpSeg14N1; nCount = 5; } break; case 6: case 7: if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg14N6S; lpType = TpSeg14N6S; nCount = 6; } else { lpSegPoints = PtSeg14N6; lpType = TpSeg14N6; nCount = 6; } break; case 8: case 9: case 11: case 12: if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg14N8S; lpType = TpSeg14N8S; nCount = 10; } else { lpSegPoints = PtSeg14N8; lpType = TpSeg14N8; nCount = 4; } break; case 13: case 10: if (iDispStyle & CDigistring::DS_SMOOTH) { lpSegPoints = PtSeg14N13S; lpType = TpSeg14N13S; nCount = 17; } else { lpSegPoints = PtSeg14N13; lpType = TpSeg14N13; nCount = 4; } break; } switch(i) { case 5: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorY(lpSegPoints[p], 41);break; case 2: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorX(lpSegPoints[p], (m_Width-1)/2);break; case 3: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorY(lpSegPoints[p], 41);break; case 4: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = PointMirror(lpSegPoints[p], CPoint((m_Width-1)/2, 41));break; case 7: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorX(lpSegPoints[p], (m_Width-1)/2);break; case 9: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorY(lpSegPoints[p], 41);break; case 11: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = PointMirror(lpSegPoints[p], CPoint((m_Width-1)/2, 41));break; case 12: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorX(lpSegPoints[p], (m_Width-1)/2);break; case 10: lpTmpSegPoints = new CPoint[nCount]; for (p = 0; p < nCount; p++) lpTmpSegPoints[p] = LineMirrorY(lpSegPoints[p], 41);break; } if (lpTmpSegPoints == NULL) x.DefPoints(lpSegPoints, lpType, nCount); else { x.DefPoints(lpTmpSegPoints, lpType, nCount); delete[] lpTmpSegPoints; lpTmpSegPoints = NULL; } m_SegmentVector.push_back(x); } m_wSegmData = wSegmData; } ///////////////////////////////////////////////////////////////////////////// // CDigiSemiColonCombi CDigiColonDotChar::CDigiColonDotChar() { m_Width = 18; m_NSegments = 3; } void CDigiColonDotChar::SetElementData(WORD wSegmData, int /*iDispStyle*/) { int i; CDSegment DSegment; LPPOINT lpSegPoints; LPBYTE lpType; int nCount; m_SegmentVector.clear(); for (i = 0; i < m_NSegments; i++) { switch(i) { case 0:lpSegPoints = PtSegScN0; lpType = TpSegScN0; nCount = 4; break; case 1: lpSegPoints = PtSegScN1; lpType = TpSegScN1; nCount = 4; break; case 2: lpSegPoints = PtSegScN2; lpType = TpSegScN2; nCount = 4; break; } DSegment.DefPoints(lpSegPoints, lpType, nCount); m_SegmentVector.push_back(DSegment); } m_wSegmData = wSegmData; } ///////////////////////////////////////////////////////////////////////////// // CDigistring CDigistring::CDigistring() : m_strText("EMPTY") { m_DispStyle = DS_SZ_PROP; m_BackColor = BLACK; m_Modified = TRUE; m_OffColor = DARKGREEN; m_OnColor = LIGHTGREEN; } CDigistring::~CDigistring() { m_CharVector.clear(); } void CDigistring::SetText(LPCTSTR lpszText) { if (m_strText != lpszText) { m_strText = lpszText; m_Modified = TRUE; Invalidate(); } } void CDigistring::Format(LPCTSTR lpszFormat, ...) { TCHAR szMessage[256]; va_list argp; va_start(argp, lpszFormat); _vsntprintf(szMessage, 255, lpszFormat, argp); va_end(argp); SetText(szMessage); } void CDigistring::SetColor(COLORREF OffColor, COLORREF OnColor) { if (m_OnColor == OnColor && m_OffColor == OffColor) return; m_OnColor = OnColor; m_OffColor = OffColor; Invalidate(); } void CDigistring::SetBackColor(COLORREF BackColor /* = BLACK */) { if (m_BackColor == BackColor) return; m_BackColor = BackColor; Invalidate(); } BOOL CDigistring::ModifyDigiStyle(DWORD dwRemove, DWORD dwAdd) { ASSERT(!(dwRemove & dwAdd)); if (dwRemove & dwAdd) return FALSE; m_DispStyle |= dwAdd; m_DispStyle &= ~dwRemove; m_Modified = TRUE; Invalidate(); return TRUE; } CDigiChar * CDigistring::DefineChar(TCHAR cChar) { int iIndex; CDigiChar * pDChar = NULL; if (cChar >= _T('0') && cChar <= _T('9') || cChar == _T(' ') || cChar == _T('-')) { if (cChar == _T(' ')) { iIndex = 0; } else if (cChar == _T('-')) { iIndex = 11; } else { iIndex = cChar - _T('0') + 1; } if (m_DispStyle & DS_STYLE14) { pDChar = new CDigi14Segment; pDChar->SetElementData(CHAR_SEGM14[iIndex], m_DispStyle); } else { pDChar = new CDigi7Segment; pDChar->SetElementData(CHAR_SEGM7[iIndex], m_DispStyle); } } else if (cChar >= _T('A') && cChar <= _T('Z')) { iIndex = cChar - _T('A') + 12; pDChar = new CDigi14Segment; pDChar->SetElementData(CHAR_SEGM14[iIndex], m_DispStyle); } else { iIndex = 0; switch(cChar) { case _T(':'): iIndex++; case _T('.'): pDChar = new CDigiColonDotChar; pDChar->SetElementData(CHAR_SEMCOL[iIndex], m_DispStyle); break; case _T('*'): iIndex = MAXSEGCHAR14 - 2; pDChar = new CDigi14Segment; pDChar->SetElementData(CHAR_SEGM14[iIndex], m_DispStyle); break; case _T('+'): iIndex = MAXSEGCHAR14 - 1; pDChar = new CDigi14Segment; pDChar->SetElementData(CHAR_SEGM14[iIndex], m_DispStyle); break; default : ASSERT(FALSE); } } return pDChar; } void CDigistring::BuildString() { CDigiChar * pDChar; if (!m_Modified) return; m_CharVector.clear(); m_strText.MakeUpper(); for (int i = 0; i < m_strText.GetLength(); i++) { if ((pDChar = DefineChar(m_strText[i])) != NULL) { m_CharVector.push_back(*pDChar); delete pDChar; } } m_Modified = FALSE; } BEGIN_MESSAGE_MAP(CDigistring, CStatic) //{{AFX_MSG_MAP(CDigistring) ON_WM_PAINT() ON_WM_ERASEBKGND() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDigistring message handlers void CDigistring::OnPaint() { CRect rect; CDoubleRect CharRect; GetClientRect(&rect); CPaintDC dc(this); // device context for painting dc.SetBkColor(m_BackColor); CMemDC memDC(&dc, &rect); CBrush hBrushOff, hBrushOn; hBrushOff.CreateSolidBrush(m_OffColor); hBrushOn.CreateSolidBrush(m_OnColor); CBrush *pOldBrush = memDC.SelectObject(&hBrushOn); int r = int(GetRValue(m_OffColor) * 0.75 + GetRValue(m_BackColor) * 0.25); int g = int(GetGValue(m_OffColor) * 0.75 + GetGValue(m_BackColor) * 0.25); int b = int(GetBValue(m_OffColor) * 0.75 + GetBValue(m_BackColor) * 0.25); CPen OffPen(PS_SOLID | PS_ENDCAP_ROUND, 1, RGB(r,g,b)); r = int(GetRValue(m_OnColor) * 0.75 + GetRValue(m_BackColor) * 0.25); g = int(GetGValue(m_OnColor) * 0.75 + GetGValue(m_BackColor) * 0.25); b = int(GetBValue(m_OnColor) * 0.75 + GetBValue(m_BackColor) * 0.25); CPen OnPen(PS_SOLID | PS_ENDCAP_ROUND, 1, RGB(r,g,b)); CPen *pOldPen = memDC.SelectObject(&OffPen); int iTotWidth = 0; double dRelWidth, dRelHeight; // TODO: Add your message handler code here DigiCharVector::iterator CharIterator; // Calculate resizing factors... BuildString(); for (CharIterator = m_CharVector.begin(); CharIterator != m_CharVector.end(); CharIterator++) { iTotWidth += CharIterator->GetNormWidth(); } dRelWidth = double(rect.Width()) / iTotWidth; dRelHeight = double(rect.Height()) / NORM_DIGIHEIGHT; // If proportional make offset for centered text if (m_DispStyle & DS_SZ_PROP) { if (dRelWidth < dRelHeight) dRelHeight = dRelWidth; else dRelWidth = dRelHeight; CharRect.left = (rect.Width() - dRelWidth * iTotWidth) / 2; CharRect.top = (rect.Height() - dRelHeight * NORM_DIGIHEIGHT) / 2; } else CharRect.SetRectEmpty(); // Draw all characters... for (CharIterator = m_CharVector.begin(); CharIterator != m_CharVector.end(); CharIterator++) { CharRect.SetRect(CharRect.left, CharRect.top, CharRect.left + dRelWidth * CharIterator->GetNormWidth(), CharRect.top + dRelHeight * NORM_DIGIHEIGHT); CharIterator->Draw(&memDC, CharRect, &OffPen, &OnPen, &hBrushOff, &hBrushOn); CharRect.left += dRelWidth * CharIterator->GetNormWidth(); } // Mama says: Clean up your mess! memDC.SelectObject(pOldPen); memDC.SelectObject(pOldBrush); OffPen.DeleteObject(); OnPen.DeleteObject(); hBrushOff.DeleteObject(); hBrushOn.DeleteObject(); } BOOL CDigistring::OnEraseBkgnd(CDC* /*pDC*/) { // Don't erase the background to avoid flickering // Background is painted in CMemDC::CMemDC(); with FillSolidRect(); return FALSE; }