mEdit.cpp
上传用户:szth180
上传日期:2007-01-02
资源大小:23k
文件大小:16k
源码类别:

编辑框

开发平台:

Visual C++

  1. // mEdit.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "mEdit.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #undef THIS_FILE
  8. static char THIS_FILE[] = __FILE__;
  9. #endif
  10. /////////////////////////////////////////////////////////////////////////////
  11. // CmEdit
  12. void AFXAPI DDX_CmEdit(CDataExchange* pDX, int nIDC, CmEdit& rControl, CString& data)
  13. {
  14.     DDX_Control(pDX, nIDC, (CWnd&)rControl);
  15.     if (!pDX->m_bSaveAndValidate)
  16.     {
  17.         rControl.SetData(data);
  18.     }
  19.     else
  20.     {
  21.         data = rControl.GetData();
  22.     }
  23. }
  24. IMPLEMENT_DYNCREATE(CmEdit, CEdit)
  25. CmEdit::CmEdit()
  26.   : m_bInit(false),
  27.     m_strPrompt("_"),
  28.     m_iNumChars(0),
  29.     m_iCurrentChar(0),
  30.     m_bShiftDown(false)
  31. {
  32.     for (int i = 0; i < MAX_CHARS; i++)
  33.         m_Char[i] = NULL;
  34.     //SubclassWindow(pParent->m_hWnd);
  35.     //pParent->SubclassWindow(this->m_hWnd);
  36. }
  37. CmEdit::~CmEdit()
  38. {
  39.     for (int i = 0; i < MAX_CHARS; i++)
  40.         if (m_Char[i] != NULL)
  41.         {
  42.             delete m_Char[i];
  43.             m_Char[i] = NULL;
  44.         }
  45. }
  46. BEGIN_MESSAGE_MAP(CmEdit, CEdit)
  47. //{{AFX_MSG_MAP(CmEdit)
  48. ON_WM_CHAR()
  49. ON_WM_KEYDOWN()
  50. ON_WM_CREATE()
  51. ON_WM_DESTROY()
  52. ON_WM_SETFOCUS()
  53. ON_WM_LBUTTONUP()
  54. ON_WM_KEYUP()
  55. ON_WM_LBUTTONDBLCLK()
  56. //}}AFX_MSG_MAP
  57. END_MESSAGE_MAP()
  58. /////////////////////////////////////////////////////////////////////////////
  59. // CmEdit message handlers
  60. int CmEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  61. {
  62. if (CEdit::OnCreate(lpCreateStruct) == -1)
  63. return -1;
  64.     return 0;
  65. }
  66. void CmEdit::OnDestroy() 
  67. {
  68. CEdit::OnDestroy();
  69. }
  70. BOOL CmEdit::PreCreateWindow(CREATESTRUCT& cs) 
  71. {
  72.     cs.style |= WS_TABSTOP | WS_VISIBLE | WS_DISABLED | ES_AUTOHSCROLL;
  73.     cs.dwExStyle |= WS_EX_OVERLAPPEDWINDOW;
  74.     
  75. return CEdit::PreCreateWindow(cs);
  76. }
  77. void CmEdit::SetData(const CString& data)
  78. {
  79.     CString strWindowText;
  80.     CString strData;
  81.     int     iNextDataChar = 0;
  82.     
  83.     for (int i = 1; i <= m_iNumChars; i++)
  84.     {
  85.         if (m_Char[i - 1]->m_bStaticChar)
  86.         {
  87.             strWindowText += m_Char[i - 1]->m_strValids;
  88.         }
  89.         else
  90.         {
  91.             if (iNextDataChar < data.GetLength())
  92.             {
  93.                 strData = data[iNextDataChar++];
  94.                 if (m_Char[i - 1]->m_strValids.Find(strData[0]) < 0)
  95.                     strData = m_strPrompt;
  96.             }
  97.             else
  98.             {
  99.                 strData = m_strPrompt;
  100.             }
  101.             
  102.             strWindowText += strData[0];
  103.         }
  104.     }
  105.     SetWindowText(strWindowText);
  106. }
  107. CString CmEdit::GetData()
  108. {
  109.     CString strWindowText;
  110.     GetWindowText(strWindowText);
  111.     CString strData;
  112.     
  113.     for (int i = 1; i <= m_iNumChars; i++)
  114.     {
  115.         if (!m_Char[i - 1]->m_bStaticChar)
  116.         {
  117.             if (strWindowText.GetLength() >= i)
  118.             {
  119.                 if (strWindowText[i - 1] != m_strPrompt)
  120.                     strData += strWindowText[i - 1];
  121.             }
  122.             else
  123.                 strData += m_strPrompt;
  124.         }
  125.     }
  126.     return strData;
  127. }
  128. void CmEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
  129. {
  130.     switch (nChar)
  131.     {
  132.     case VK_TAB:
  133.                 //(((CWnd*)GetParent())->GetNextDlgTabItem(this, m_bShiftDown))->SetFocus();
  134.                 break;
  135.     
  136.     case VK_BACK:
  137.                 if (m_iCurrentChar > 0)
  138.                 {
  139.                     int iNewNext = FindNextChar(m_iCurrentChar - 1, false, false);
  140.                     if (iNewNext >= 0)
  141.                     {
  142.                         SetSel(iNewNext, iNewNext + 1);
  143.                         ReplaceSel(m_strPrompt);
  144.                         m_iCurrentChar = iNewNext;
  145.                         SetSel(m_iCurrentChar, m_iCurrentChar);
  146.                     }
  147.                 }
  148.                 break;
  149.     default:    
  150.                 int x, y, z;
  151.                 GetSel(x,y);
  152.                 if (x != y)
  153.                 {
  154.                     CString szReplaceText = "";
  155.                     for (z = x; z < y; z++)
  156.                     {
  157.                         if (m_Char[z]->m_bStaticChar)
  158.                         {
  159.                             szReplaceText += m_Char[z]->m_strValids;
  160.                         }
  161.                         else
  162.                         {
  163.                             szReplaceText += m_strPrompt;
  164.                         }
  165.                     }
  166.                     ReplaceSel(szReplaceText);
  167.                     m_iCurrentChar = FindNextChar(x, false, true);
  168.                     SetSel(m_iCurrentChar, m_iCurrentChar);
  169.                 }
  170.         
  171.         
  172.                 if (m_iCurrentChar < m_iNumChars)
  173.                 {
  174.                     if ( m_Char[m_iCurrentChar]->m_strValids.Find((TCHAR)nChar) >= 0 )
  175.                     {
  176.                         int iNewNext = FindNextChar(m_iCurrentChar + 1, false, true);
  177.                         SetSel(m_iCurrentChar, m_iCurrentChar + 1);
  178.                         ReplaceSel((CString)(char)nChar);
  179.                         if (iNewNext >= 0)
  180.                         {
  181.                             m_iCurrentChar = iNewNext;
  182.                         }
  183.                         else
  184.                         {
  185.                             m_iCurrentChar++;
  186.                         }
  187.                         SetSel(m_iCurrentChar, m_iCurrentChar);
  188.                     }
  189.                 }
  190.                 break;
  191.     }
  192.     //CEdit::OnChar(nChar, nRepCnt, nFlags);
  193. }
  194. void CmEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
  195. {
  196.     switch (nChar)
  197.     {
  198.     case VK_SHIFT:
  199.                 m_bShiftDown = false;
  200.                 break;
  201.     
  202.     default:
  203.                 break;
  204.     }
  205.     
  206. CEdit::OnKeyUp(nChar, nRepCnt, nFlags);
  207. }
  208. void CmEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  209. {
  210.     int iNext = 0;
  211.     CWnd* pNextItem = NULL;
  212.     
  213.     switch (nChar)
  214.     {
  215.     // Tab key
  216.     case VK_TAB:
  217.                 pNextItem = (((CWnd*)GetParent())->GetNextDlgTabItem(this, (m_bShiftDown) ? TRUE : FALSE));
  218.                 if (pNextItem->IsKindOf(RUNTIME_CLASS(CmEdit)))
  219.                     ((CmEdit*)pNextItem)->m_bShiftDown = m_bShiftDown;
  220.                 (((CWnd*)GetParent())->GetNextDlgTabItem(this, (m_bShiftDown) ? TRUE : FALSE))->SetFocus();
  221.                 break;
  222.         
  223.     // Shift key
  224.     case VK_SHIFT:
  225.                 m_bShiftDown = true;
  226.                 break;
  227.         
  228.     // Left arrow key
  229.     case VK_LEFT:
  230.                 iNext = FindNextChar(m_iCurrentChar - 1, false, false);
  231.                 if (iNext >= 0)
  232.                 {
  233.                     m_iCurrentChar = iNext;
  234.                     SetSel(m_iCurrentChar, m_iCurrentChar);
  235.                 }
  236.                 break;
  237.     
  238.     // Right arrow key
  239.     case VK_RIGHT:
  240.                 iNext = FindNextChar(m_iCurrentChar + 1, false, true);
  241.                 if (iNext >= 0)
  242.                     m_iCurrentChar = iNext;
  243.                 else
  244.                 {
  245.                     m_iCurrentChar = FindNextChar(m_iNumChars - 1, false, false) + 1;
  246.                 }
  247.                 SetSel(m_iCurrentChar, m_iCurrentChar);
  248.                 break;
  249.     // Home key
  250.     case VK_HOME:
  251.                 if (m_bShiftDown)
  252.                 {
  253.                     SetSel(0, m_iCurrentChar);
  254.                 }
  255.                 else
  256.                 {
  257.                     m_iCurrentChar = FindNextChar(0, false, true);
  258.                     SetSel(m_iCurrentChar, m_iCurrentChar);
  259.                 }
  260.                 break;
  261.     // End key
  262.     case VK_END:
  263.                 if (m_bShiftDown)
  264.                 {
  265.                     int iLast = FindNextChar(m_iNumChars - 1, false, false) + 1;
  266.                     SetSel(m_iCurrentChar, iLast);
  267.                 }
  268.                 else
  269.                 {
  270.                     m_iCurrentChar = FindNextChar(m_iNumChars - 1, false, false) + 1;
  271.                     SetSel(m_iCurrentChar, m_iCurrentChar);
  272.                 }
  273.                 break;
  274.     // Insert key
  275.     case VK_INSERT:
  276.                 break;
  277.     // Delete key
  278.     case VK_DELETE:
  279.                 int x, y, z;
  280.                 GetSel(x,y);
  281.                 if (x != y)
  282.                 {
  283.                     CString szReplaceText = "";
  284.                     for (z = x; z < y; z++)
  285.                     {
  286.                         if (m_Char[z]->m_bStaticChar)
  287.                         {
  288.                             szReplaceText += m_Char[z]->m_strValids;
  289.                         }
  290.                         else
  291.                         {
  292.                             szReplaceText += m_strPrompt;
  293.                         }
  294.                     }
  295.                     ReplaceSel(szReplaceText);
  296.                     m_iCurrentChar = FindNextChar(x, false, true);
  297.                     SetSel(m_iCurrentChar, m_iCurrentChar);
  298.                 }
  299.                 else if (m_iCurrentChar <= FindNextChar(m_iNumChars - 1, false, false))
  300.                 {
  301.                     SetSel(m_iCurrentChar, m_iCurrentChar + 1);
  302.                     ReplaceSel(m_strPrompt);
  303.                     iNext = FindNextChar(m_iCurrentChar + 1, false, true);
  304.                     if (iNext >= 0)
  305.                         m_iCurrentChar = iNext;
  306.                     else
  307.                         m_iCurrentChar++;
  308.                     SetSel(m_iCurrentChar, m_iCurrentChar);
  309.                 }
  310.                 break;
  311.     default:
  312.                 break;
  313.     }
  314.     //CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
  315. }
  316. bool CmEdit::Init(CString strMask, CString strInitialData)
  317. {
  318.     m_bInit = false;
  319.     
  320.     if (!Parse(strMask))
  321.     {
  322.         SetWindowText("Init failed.");
  323.         EnableWindow(FALSE);
  324.         return false;
  325.     }
  326.     if (!SetValidChars(strMask))
  327.     {
  328.         SetWindowText("SetValidChars failed.");
  329.         EnableWindow(FALSE);
  330.         return false;                          
  331.     }
  332.     
  333.     SetData(strInitialData);
  334.     m_iCurrentChar = FindNextChar(0, false, true);
  335.     this->SetFocus();
  336.     SetSel(m_iCurrentChar, m_iCurrentChar);
  337.     EnableWindow(TRUE);  // this line is important!
  338.     m_bInit = true;
  339.     return true;
  340. }
  341. int CmEdit::FindNextChar(int iStartPos, bool bStatic, bool bForward)
  342. {
  343.     int iIndex = 0;
  344.     int iReturnVal = -1;
  345.     
  346.     if (bForward)
  347.     {
  348.         for (int iIndex = iStartPos; iIndex < m_iNumChars; iIndex++)
  349.         {
  350.             if (m_Char[iIndex]->m_bStaticChar == bStatic)
  351.             {
  352.                 iReturnVal = iIndex;
  353.                 break;
  354.             }
  355.         }
  356.     }
  357.     else
  358.     {
  359.         for (int iIndex = iStartPos; iIndex >= 0; iIndex--)
  360.         {
  361.             if (m_Char[iIndex]->m_bStaticChar == bStatic)
  362.             {
  363.                 iReturnVal = iIndex;
  364.                 break;
  365.             }
  366.         }
  367.     }
  368.     return iReturnVal;
  369. }
  370. bool CmEdit::SetValidChars(const CString& strMask)
  371. {
  372.     CString strChars;
  373.     CString strRangeLow; 
  374.     bool    bInside       = false;
  375.     bool    bInsideEscape = false;
  376.     bool    bInsideRange  = false;
  377.     int     iNextChar     = 0;
  378.     int     i;
  379.     
  380.     // Clear valid chars
  381.     for (i = 0; i < MAX_CHARS; i++)
  382.         if (m_Char[i] != NULL)
  383.         {
  384.             delete m_Char[i];
  385.             m_Char[i] = NULL;
  386.         }
  387.     // Walk through mask string
  388.     for (i = 0; i < strMask.GetLength(); i++)
  389.     {
  390.         switch (strMask[i])
  391.         {
  392.         case '[':   bInside = true;
  393.                     break;            //done
  394.         case ']':   bInside = false;
  395.                     m_Char[iNextChar++] = new CmEditChar(strChars, false);
  396.                     strChars = "";
  397.                     break;
  398.         case '-':   if (bInside)
  399.                     {
  400.                         if (bInsideEscape)
  401.                         {
  402.                             strChars += "-";
  403.                             bInsideEscape = false;  //done
  404.                         }
  405.                         else
  406.                         {
  407.                             if (strChars.GetLength() == 0)
  408.                                 return false;
  409.                             bInsideRange = true;
  410.                             strRangeLow = strChars.Right(1);
  411.                             strChars = strChars.Left(strChars.GetLength() - 1); //done
  412.                         }
  413.                     }
  414.                     else
  415.                     {
  416.                         m_Char[iNextChar++] = new CmEditChar("-", true); //done
  417.                     }
  418.                     break;
  419.         case '\':  if (bInside)
  420.                     {
  421.                         if (!bInsideEscape)
  422.                         {
  423.                             bInsideEscape = true;  //done
  424.                         }
  425.                         else
  426.                         {
  427.                             if (bInsideRange)
  428.                             {
  429.                                 strChars += GetRange(strRangeLow, "\");
  430.                                 strRangeLow = "";
  431.                                 bInsideRange = false;  //done
  432.                             }
  433.                             else
  434.                             {
  435.                                 strChars += "\";
  436.                                 bInsideEscape = false;  //done
  437.                             }
  438.                         }
  439.                     }
  440.                     else
  441.                     {
  442.                         m_Char[iNextChar++] = new CmEditChar("\", true); //done
  443.                     }
  444.                     break;
  445.         default:    if (bInside)
  446.                     {
  447.                         if (bInsideEscape)
  448.                         {
  449.                             bInsideEscape = false;        //done
  450.                         }
  451.                         if (bInsideRange)
  452.                         {
  453.                             strChars += GetRange(strRangeLow, strMask[i]);
  454.                             strRangeLow = "";
  455.                             bInsideRange = false;   //done
  456.                         }
  457.                         else
  458.                         {
  459.                             strChars += strMask[i]; //done
  460.                         }
  461.                     }
  462.                     else
  463.                     {
  464.                         m_Char[iNextChar++] = new CmEditChar(strMask[i], true); //done
  465.                     }
  466.                     break;
  467.         }
  468.     }
  469.     m_iNumChars = iNextChar;
  470.     SetLimitText(m_iNumChars);
  471.     
  472.     return true;
  473. }
  474. CString CmEdit::GetRange(CString szLow, CString szHigh)
  475. {
  476.     CString szReturn = "";
  477.     if (szLow.GetLength() == 1 && szHigh.GetLength() == 1)
  478.     {
  479.         char first = szLow[0];
  480.         char last  = szHigh[0];
  481.         for (int i = first; i <= last; i++)
  482.             szReturn += (CString)(char)i;
  483.     }
  484.     return szReturn;
  485. }
  486. bool CmEdit::Parse(const CString& strMask)
  487. {
  488.     bool bValid = true;
  489.     int iBracketState = 0;
  490.     //int iDashState = 0;
  491.     
  492.     for (int i = 1; i <= strMask.GetLength(); i++)
  493.     {
  494.         switch (strMask[i - 1])
  495.         {
  496.         case '[':   iBracketState++; break;
  497.         case ']':   iBracketState--; break;
  498.         //case '-':   if (iBracketState > 0)
  499.         //                iDashState = 1;
  500.         //            break;
  501.         default:    //if (iBracketState > 0) && iDashState == 1)
  502.                     //    iDashState = 0;
  503.                     break;
  504.         }
  505.         // Make sure the [ ] are in sync
  506.         if (iBracketState < 0 || iBracketState > 1)
  507.             bValid = false;
  508.         // Make sure there is a character after a '-' inside the [ ]
  509.         //if (iBracketState == 0 && iDashState == 1)
  510.         //    bValid = false;
  511.     }
  512.     return (iBracketState == 0 /*&& iDashState == 0*/ && bValid) ? true : false;
  513. }
  514. bool CmEdit::SetPromptChar(CString strPromptChar)
  515. {
  516.     if (strPromptChar.GetLength() != 1)
  517.         return false;
  518.     m_strPrompt = strPromptChar;
  519.     return true;
  520. }
  521. void CmEdit::OnSetFocus(CWnd* pOldWnd) 
  522. {
  523. CEdit::OnSetFocus(pOldWnd);
  524.     //SetSel(m_iCurrentChar, m_iCurrentChar);
  525.     SetSel(0, -1);
  526. }
  527. void CmEdit::OnLButtonUp(UINT nFlags, CPoint point) 
  528. {
  529. int x, y;
  530.     GetSel(x, y);
  531.     if (x == y)
  532.     {
  533.         m_iCurrentChar = x;
  534.         SetSel(m_iCurrentChar, m_iCurrentChar);
  535.     }
  536. CEdit::OnLButtonUp(nFlags, point);
  537. }
  538. void CmEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
  539. {
  540.     SetSel(0, -1);
  541. }