XTMaskEditT.h
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:34k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTMaskEditT.h interface for the CXTMaskEditT class.
  2. //
  3. // This file is a part of the XTREME TOOLKIT PRO MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. //{{AFX_CODEJOCK_PRIVATE
  21. #if !defined(__XTMASKEDITEX_H__)
  22. #define __XTMASKEDITEX_H__
  23. //}}AFX_CODEJOCK_PRIVATE
  24. #if _MSC_VER >= 1000
  25. #pragma once
  26. #endif // _MSC_VER >= 1000
  27. //////////////////////////////////////////////////////////////////////
  28. // Summary:
  29. //     CXTMaskEditT is a template class. It allows text masking to be
  30. //     applied to the control to format it for special editing restrictions.
  31. //////////////////////////////////////////////////////////////////////
  32. template <class TBase>
  33. class CXTMaskEditT : public TBase
  34. {
  35. public:
  36. //-----------------------------------------------------------------------
  37. // Summary:
  38. //     Constructs a CXTMaskEditT object
  39. //-----------------------------------------------------------------------
  40. CXTMaskEditT()
  41. : m_nStartChar(0)
  42. , m_nEndChar(0)
  43. , m_bOverType(FALSE)
  44. , m_bUseMask(TRUE)
  45. , m_bRedo(FALSE)
  46. , m_bModified(FALSE)
  47. , m_strWindowText(_T(""))
  48. , m_strMask(_T(""))
  49. , m_strLiteral(_T(""))
  50. , m_strDefault(_T(""))
  51. , m_strUndoBuffer(_T(""))
  52. , m_chPrompt(_T('_'))
  53. , m_bUpdateUndo(TRUE)
  54. {
  55. }
  56. public:
  57. //-----------------------------------------------------------------------
  58. // Parameters:
  59. //     bUseMask - TRUE to enable the mask. FALSE to disable the mask.
  60. // Summary:
  61. //     Call this member function to enable or disable the mask for the mask
  62. //     edit control.
  63. //-----------------------------------------------------------------------
  64. void SetUseMask(BOOL bUseMask) {
  65. m_bUseMask = bUseMask;
  66. }
  67. //-----------------------------------------------------------------------
  68. // Summary:
  69. //     This member function is called to determine if the mask for the edit
  70. //     control can be used.
  71. // Returns:
  72. //     TRUE if the mask can be used, otherwise returns FALSE.
  73. //-----------------------------------------------------------------------
  74. BOOL CanUseMask() const {
  75. return m_bUseMask && m_hWnd && ((GetStyle() & ES_READONLY) == 0) && !m_strMask.IsEmpty();
  76. }
  77. //-----------------------------------------------------------------------
  78. // Summary:
  79. //     This member function is called to enable or disable type over, also
  80. //     known as insert mode.
  81. // Parameters:
  82. //     bOverType - TRUE to enable type over.
  83. //-----------------------------------------------------------------------
  84. void SetOverType(BOOL bOverType) {
  85. m_bOverType = bOverType;
  86. }
  87. //-----------------------------------------------------------------------
  88. // Summary:
  89. //     This member function is called to determine if type over has been enabled.
  90. // Returns:
  91. //     TRUE if type over is enabled, otherwise returns FALSE.
  92. //-----------------------------------------------------------------------
  93. BOOL CanOverType() const {
  94. return m_bOverType;
  95. }
  96. //-----------------------------------------------------------------------
  97. // Summary:
  98. //     This member function is called to determine if the index specified
  99. //     by 'iPos' is a valid index for the currently displayed edit text.
  100. // Parameters:
  101. //     iPos - Index of the character to check.
  102. // Returns:
  103. //     TRUE if the index is valid, otherwise returns FALSE.
  104. //-----------------------------------------------------------------------
  105. BOOL PosInRange(int iPos) const {
  106. return ((iPos >= 0) && (iPos < m_strLiteral.GetLength()));
  107. }
  108. //-----------------------------------------------------------------------
  109. // Summary:
  110. //     This member function retrieves the character that is currently used as
  111. //     the mask prompt. The mask prompt indicates that the field is editable.
  112. // Returns:
  113. //     A TCHAR data type.
  114. //-----------------------------------------------------------------------
  115. TCHAR GetPromptChar() const {
  116. return m_chPrompt;
  117. }
  118. //-----------------------------------------------------------------------
  119. // Summary:
  120. //     This helper member function retrieves the string contains nLength prompt characters.
  121. // Parameters:
  122. //     nLength - Length of string to create.
  123. // Returns:
  124. //     CString contains nLength prompt characters
  125. //-----------------------------------------------------------------------
  126. CString GetPromptString(int nLength) const {
  127. CString strPrompt;
  128. while (nLength--)
  129. strPrompt += m_chPrompt;
  130. return strPrompt;
  131. }
  132. //-----------------------------------------------------------------------
  133. // Summary:
  134. //     This member function is called to set the prompt character that is
  135. //     displayed to the user that indicates the field can be edited.
  136. // Parameters:
  137. //     ch - A TCHAR data type.
  138. //     bAutoReplace - TRUE to auto replace
  139. //-----------------------------------------------------------------------
  140. void SetPromptChar(TCHAR ch, BOOL bAutoReplace = TRUE)
  141. {
  142. if (m_chPrompt == ch)
  143. return;
  144. if (bAutoReplace)
  145. {
  146. GetMaskState();
  147. for (int i = 0; i < m_strLiteral.GetLength(); i++)
  148. if (m_strLiteral[i] == m_chPrompt) m_strLiteral.SetAt(i, ch);
  149. for (int j = 0; j < m_strWindowText.GetLength(); j++)
  150. if (m_strWindowText[j] == m_chPrompt) m_strWindowText.SetAt(j, ch);
  151. SetMaskState();
  152. }
  153. m_chPrompt = ch;
  154. }
  155. //-----------------------------------------------------------------------
  156. // Summary:
  157. //     This member function is called to perform a cut operation using the
  158. //     currently selected text.
  159. //-----------------------------------------------------------------------
  160. afx_msg BOOL MaskCut()
  161. {
  162. if (!CanUseMask())
  163. return (BOOL)DefWindowProc(WM_CUT, 0, 0);
  164. MaskCopy();
  165. MaskClear();
  166. return TRUE;
  167. }
  168. //-----------------------------------------------------------------------
  169. // Summary:
  170. //     This member function is called to perform a copy operation using the
  171. //     currently selected text.
  172. //-----------------------------------------------------------------------
  173. afx_msg BOOL MaskCopy()
  174. {
  175. if (!CanUseMask())
  176. return (BOOL)DefWindowProc(WM_COPY, 0, 0);
  177. GetMaskState();
  178. CString strMaskedText = GetMaskedText(m_nStartChar, m_nEndChar);
  179. CopyToClipboard(strMaskedText);
  180. return TRUE;
  181. }
  182. //-----------------------------------------------------------------------
  183. // Summary:
  184. //     This member function is called to perform a replace operation using the
  185. //     currently selected text.
  186. // Parameters:
  187. //     lpszNewText - Text to replace.
  188. //-----------------------------------------------------------------------
  189. void MaskReplaceSel(LPCTSTR lpszNewText)
  190. {
  191. ASSERT(CanUseMask());
  192. if (m_nStartChar != m_nEndChar)
  193. MaskDeleteSel();
  194. int x = m_nStartChar, nNewTextLen = (int)_tcslen(lpszNewText);
  195. int nWindowTextLen = m_strWindowText.GetLength();
  196. if (x >= nWindowTextLen)
  197. return;
  198. for (int i = 0; i < nNewTextLen; ++i)
  199. {
  200. TCHAR ch = lpszNewText[i];
  201. if (ch == m_chPrompt || CheckChar(ch, x))
  202. {
  203. InsertCharAt(x, ch);
  204. x++;
  205. while (x < nWindowTextLen && !IsPromptPos(x))
  206. x++;
  207. if (x >= m_strWindowText.GetLength())
  208. break;
  209. }
  210. }
  211. CorrectPosition(x);
  212. m_nStartChar = m_nEndChar = x;
  213. }
  214. //-----------------------------------------------------------------------
  215. // Summary:
  216. //     This member function is called to perform a paste operation using the
  217. //     current clipboard text.
  218. //-----------------------------------------------------------------------
  219. afx_msg BOOL MaskPaste()
  220. {
  221. if (!CanUseMask())
  222. return (BOOL)DefWindowProc(WM_PASTE, 0, 0);
  223. GetMaskState();
  224. if (!OpenClipboard())
  225. return FALSE;
  226. #ifndef _UNICODE
  227. HGLOBAL hglbPaste = ::GetClipboardData(CF_TEXT);
  228. #else
  229. HGLOBAL hglbPaste = ::GetClipboardData(CF_UNICODETEXT);
  230. #endif
  231. if (hglbPaste != NULL)
  232. {
  233. TCHAR* lpszClipboard = (TCHAR*)GlobalLock(hglbPaste);
  234. MaskReplaceSel(lpszClipboard);
  235. GlobalUnlock(hglbPaste);
  236. SetMaskState();
  237. }
  238. ::CloseClipboard();
  239. return TRUE;
  240. }
  241. //-----------------------------------------------------------------------
  242. // Summary:
  243. //     This member function is called to delete the selection.
  244. //-----------------------------------------------------------------------
  245. void MaskDeleteSel()
  246. {
  247. if (m_nStartChar == m_nEndChar)
  248. return;
  249. CString strMaskedText = GetMaskedText(m_nEndChar);
  250. SetMaskedText(strMaskedText, m_nStartChar, FALSE);
  251. m_nEndChar = m_nStartChar;
  252. }
  253. //-----------------------------------------------------------------------
  254. // Summary:
  255. //     This member function is called to clear the current text selection.
  256. //-----------------------------------------------------------------------
  257. afx_msg BOOL MaskClear()
  258. {
  259. if (!CanUseMask())
  260. return (BOOL)DefWindowProc(WM_CLEAR, 0, 0);
  261. GetMaskState();
  262. MaskDeleteSel();
  263. SetMaskState();
  264. return TRUE;
  265. }
  266. //-----------------------------------------------------------------------
  267. // Summary:
  268. //     This member function is called to undo the previous action.
  269. //-----------------------------------------------------------------------
  270. afx_msg BOOL MaskUndo()
  271. {
  272. if (!CanUseMask())
  273. {
  274. return (BOOL)DefWindowProc(EM_UNDO, 0, 0);
  275. }
  276. else
  277. {
  278. MaskGetSel();
  279. if (m_bRedo)
  280. {
  281. SetWindowText(m_strRedoBuffer);
  282. }
  283. else
  284. {
  285. GetWindowText(m_strRedoBuffer);
  286. SetWindowText(m_strUndoBuffer);
  287. }
  288. m_bRedo = !m_bRedo;
  289. m_bModified = TRUE;
  290. m_nEndChar = m_nStartChar;
  291. SetSel(m_nStartChar, m_nEndChar);
  292. }
  293. return TRUE;
  294. }
  295. //-----------------------------------------------------------------------
  296. // Summary:
  297. //     This member function is called to select all text in the mask edit
  298. //     control.
  299. //-----------------------------------------------------------------------
  300. afx_msg void MaskSelectAll()
  301. {
  302. if (!CanUseMask())
  303. {
  304. SetSel(0, -1);
  305. }
  306. else
  307. {
  308. m_nStartChar = 0;
  309. CorrectPosition(m_nStartChar);
  310. SetSel(m_nStartChar, -1);
  311. }
  312. }
  313. //-----------------------------------------------------------------------}
  314. // Summary:
  315. //     This member function is called to determine if the text has been modified.
  316. // Returns:
  317. //     TRUE if the text has changed, otherwise returns FALSE.
  318. //-----------------------------------------------------------------------
  319. BOOL IsModified() const {
  320. return m_bModified;
  321. }
  322. //-----------------------------------------------------------------------
  323. // Summary:
  324. //     This method called to set masked text for the edit control.
  325. // Parameters:
  326. //     lpszMaskedText - Text string without mask.
  327. //     iPos          - Start position from which current masked text
  328. //                     will be updated.
  329. //                     Default value 0 (the first position).
  330. //     bUpdateWindow - If TRUE - edit control window text and selection
  331. //                     will be updated, otherwise only internal members
  332. //                     take changes.
  333. // Remarks:
  334. //     If a mask is used, then the mask will be applied to the text
  335. //     in lpszMaskedText.
  336. //-----------------------------------------------------------------------
  337. void SetMaskedText(LPCTSTR lpszMaskedText, int iPos = 0, BOOL bUpdateWindow = TRUE)
  338. {
  339. int nMaskedTextLength = (int)_tcslen(lpszMaskedText);
  340. m_strWindowText = m_strWindowText.Left(iPos);
  341. int nIndex = 0;
  342. for (; (iPos <  m_strLiteral.GetLength()) && (nIndex < nMaskedTextLength) ; iPos++)
  343. {
  344. TCHAR uChar = lpszMaskedText[nIndex];
  345. if (IsPromptPos(iPos) && ((uChar == m_chPrompt) || ProcessMask(uChar, iPos)))
  346. {
  347. m_strWindowText += (TCHAR)uChar;
  348. nIndex ++;
  349. }
  350. else
  351. {
  352. m_strWindowText += m_strLiteral[iPos];
  353. }
  354. }
  355. if (bUpdateWindow)
  356. {
  357. SetMaskState(FALSE);
  358. }
  359. else
  360. {
  361. CorrectWindowText();
  362. }
  363. }
  364. //-----------------------------------------------------------------------
  365. // Summary:
  366. //     This member function will set the mask for the edit control.
  367. // Parameters:
  368. //     lpszMask    - The format for the mask field. For example, if you wanted to set
  369. //                   the mask for a phone number, and you only wanted digits to be entered,
  370. //                   your mask might look like this; _T("(000) 000-0000").
  371. //     lpszLiteral - The literal format is entered here. Wherever you place an underscore
  372. //                   ('_') is where the user will be allowed to enter data only. Using
  373. //                   the phone number example; _T("(___) ___-____").
  374. //     lpszDefault - Text that is to be displayed when the control is initialized. For
  375. //                   example; _T("(800) 555-1212"). If NULL, 'lpszLiteral' is used to initialize
  376. //                   the edit text.
  377. // Remarks:
  378. //     The values that can be set are:
  379. //     <TABLE>
  380. //          <b>Mask Character</b>  <b>Description</b>
  381. //          ---------------------  ------------------------
  382. //          0                      Numeric (0-9)
  383. //          9                      Numeric (0-9) or space (' ')
  384. //          #                      Numeric (0-9) or space (' ') or ('+') or ('-')
  385. //          L                      Alpha (a-Z)
  386. //          ?                      Alpha (a-Z) or space (' ')
  387. //          A                      Alpha numeric (0-9 and a-Z)
  388. //          a                      Alpha numeric (0-9 and a-Z) or space (' ')
  389. //          &                      All print character only
  390. //          H                      Hex digit (0-9 and A-F)
  391. //          X                      Hex digit (0-9 and A-F) and space (' ')
  392. //          >                      Forces characters to upper case (A-Z)
  393. //          <                      Forces characters to lower case (a-z)
  394. //     </TABLE>
  395. //-----------------------------------------------------------------------
  396. virtual BOOL SetEditMask(LPCTSTR lpszMask, LPCTSTR lpszLiteral, LPCTSTR lpszDefault=NULL)
  397. {
  398. ASSERT(lpszMask);
  399. ASSERT(lpszLiteral);
  400. // initialize the mask for the control.
  401. m_strMask    = lpszMask;
  402. m_strLiteral = lpszLiteral;
  403. ASSERT(m_strMask.GetLength() == m_strLiteral.GetLength());
  404. if (m_strMask.GetLength() != m_strLiteral.GetLength())
  405. return FALSE;
  406. if (lpszDefault == NULL)
  407. {
  408. m_strWindowText = m_strDefault = lpszLiteral;
  409. }
  410. else
  411. {
  412. m_strWindowText = m_strDefault = lpszDefault;
  413. if (m_strDefault.GetLength() != m_strLiteral.GetLength())
  414. {
  415. SetMaskedText(m_strDefault, 0, FALSE);
  416. m_strDefault = m_strWindowText;
  417. }
  418. }
  419. ASSERT(m_strWindowText.GetLength() == m_strLiteral.GetLength());
  420. // set the window text for the control.
  421. m_bRedo = FALSE;
  422. m_bModified = FALSE;
  423. SetWindowText(m_strWindowText);
  424. m_strUndoBuffer = m_strWindowText;
  425. return TRUE;
  426. }
  427. //-----------------------------------------------------------------------
  428. // Summary:
  429. //     Converts character to Upper/Lower case.
  430. // Parameters:
  431. //     nChar - Char to be converted
  432. //     bUpperCase  - TRUE to convert to upper case
  433. // Returns:
  434. //     Converted character.
  435. //-----------------------------------------------------------------------
  436. TCHAR ConvertUnicodeAlpha(TCHAR nChar, BOOL bUpperCase) const
  437. {
  438. CString strTemp(nChar);
  439. if (bUpperCase) strTemp.MakeUpper(); else strTemp.MakeLower();
  440. return strTemp[0];
  441. }
  442. //-----------------------------------------------------------------------
  443. // Summary:
  444. //     This member function is used internally to validate the character indicated
  445. //     by 'nChar'.
  446. // Parameters:
  447. //     nChar - Contains the character code value of the key.
  448. //     nPos - Sting length.
  449. // Returns:
  450. //     TRUE if successful, otherwise returns FALSE.
  451. //-----------------------------------------------------------------------
  452. virtual BOOL CheckChar(TCHAR& nChar, int nPos)
  453. {
  454. // do not use mask
  455. if (!CanUseMask())
  456. return FALSE;
  457. // control character, OK
  458. if (!IsPrintChar(nChar))
  459. return TRUE;
  460. // make sure the string is not longer than the mask
  461. if (nPos >= m_strMask.GetLength())
  462. return FALSE;
  463. if (!IsPromptPos(nPos))
  464. return FALSE;
  465. return ProcessMask(nChar, nPos);
  466. }
  467. //-----------------------------------------------------------------------
  468. // Summary:
  469. //     This member function is used internally to process the character passed
  470. //     in by 'nChar' whose index is specified by 'nEndPos'.
  471. // Parameters:
  472. //     nChar - Contains the character code value of the key.
  473. //     nEndPos - Index of character in display string.
  474. // Returns:
  475. //     TRUE if successful, otherwise returns FALSE.
  476. //-----------------------------------------------------------------------
  477. virtual BOOL ProcessMask(TCHAR& nChar, int nEndPos)
  478. {
  479. ASSERT(nEndPos < m_strMask.GetLength());
  480. if (nEndPos < 0 || nEndPos >= m_strMask.GetLength())
  481. return FALSE;
  482. // check the key against the mask
  483. switch (m_strMask.GetAt(nEndPos))
  484. {
  485. case '0':       // digit only //completely changed this
  486. return _istdigit(nChar);
  487. case '9':       // digit or space
  488. return _istdigit(nChar) || _istspace(nChar);
  489. case '#':       // digit or space or '+' or '-'
  490. return _istdigit(nChar) || (_istspace(nChar) || nChar == _T('-') || nChar == _T('+'));
  491. case 'd':       // decimal
  492. return _istdigit(nChar) || (_istspace(nChar) || nChar == _T('-') || nChar == _T('+') || nChar == _T('.') || nChar == _T(','));
  493. case 'L':       // alpha only
  494. return IsAlphaChar(nChar);
  495. case '?':       // alpha or space
  496. return IsAlphaChar(nChar) || _istspace(nChar);
  497. case 'A':       // alpha numeric only
  498. return _istalnum(nChar) || IsAlphaChar(nChar);
  499. case 'a':       // alpha numeric or space
  500. return _istalnum(nChar) || IsAlphaChar(nChar) || _istspace(nChar);
  501. case '&':       // all print character only
  502. return IsPrintChar(nChar);
  503. case 'H':       // hex digit
  504. return _istxdigit(nChar);
  505. case 'X':       // hex digit or space
  506. return _istxdigit(nChar) || _istspace(nChar);
  507. case '>':
  508. if (IsAlphaChar(nChar))
  509. {
  510. nChar = ConvertUnicodeAlpha(nChar, TRUE);
  511. return TRUE;
  512. }
  513. return FALSE;
  514. case '<':
  515. if (IsAlphaChar(nChar))
  516. {
  517. nChar = ConvertUnicodeAlpha(nChar, FALSE);
  518. return TRUE;
  519. }
  520. return FALSE;
  521. }
  522. return FALSE;
  523. }
  524. public:
  525. //-----------------------------------------------------------------------
  526. // Summary:
  527. //     Used by class CWinApp to translate window messages before they are dispatched to theTranslateMessage andDispatchMessage Windows functions.
  528. // Parameters:
  529. //     pMsg - Points to a MSG structure that contains the message to process.
  530. // Returns:
  531. //     Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched.
  532. //-----------------------------------------------------------------------
  533. virtual BOOL PreTranslateMessage(MSG* pMsg)
  534. {
  535. if (!CanUseMask())
  536. return TBase::PreTranslateMessage(pMsg);
  537. // intercept Ctrl+C (copy), Ctrl+V (paste), Ctrl+X (cut) and Ctrl+Z (undo)
  538. // before CEdit base class gets a hold of them.
  539. if (pMsg->message == WM_KEYDOWN)
  540. {
  541. if (::GetKeyState(VK_SUBTRACT) < 0)
  542. {
  543. OnChar('-', 1, 1);
  544. return TRUE;
  545. }
  546. if (::GetKeyState(VK_ADD) < 0)
  547. {
  548. OnChar('+', 1, 1);
  549. return TRUE;
  550. }
  551. if (::GetKeyState(VK_CONTROL) < 0)
  552. {
  553. switch (pMsg->wParam)
  554. {
  555. case 'X':
  556. case 'x':
  557. {
  558. MaskCut();
  559. return TRUE;
  560. }
  561. case 'C':
  562. case 'c':
  563. {
  564. MaskCopy();
  565. return TRUE;
  566. }
  567. case 'V':
  568. case 'v':
  569. {
  570. MaskPaste();
  571. return TRUE;
  572. }
  573. case 'Z':
  574. case 'z':
  575. {
  576. MaskUndo();
  577. return TRUE;
  578. }
  579. }
  580. }
  581. }
  582. return TBase::PreTranslateMessage(pMsg);
  583. }
  584. //-----------------------------------------------------------------------
  585. // Summary:
  586. //     Deletes character in specified position
  587. // Parameters:
  588. //     iPos - Position for character to be deleted.
  589. //-----------------------------------------------------------------------
  590. void DeleteCharAt(int iPos)
  591. {
  592. ASSERT(PosInRange(iPos));
  593. if (!PosInRange(iPos))
  594. return;
  595. CString strMaskedText = GetMaskedText(iPos + 1) + m_chPrompt;
  596. SetMaskedText(strMaskedText, iPos, FALSE);
  597. }
  598. //-----------------------------------------------------------------------
  599. // Summary:
  600. //     Inserts character to specified position.
  601. // Parameters:
  602. //     iPos - Position to insert
  603. //     nChar - Character to be inserted
  604. //-----------------------------------------------------------------------
  605. void InsertCharAt(int iPos, TCHAR nChar)
  606. {
  607. ASSERT(PosInRange(iPos));
  608. if (!PosInRange(iPos))
  609. return;
  610. CString strMaskedText = CString(nChar) + GetMaskedText(iPos);
  611. SetMaskedText(strMaskedText, iPos, FALSE);
  612. }
  613. //-----------------------------------------------------------------------
  614. // Summary:
  615. //     Copies text to system clipboard
  616. // Parameters:
  617. //     strText - Text to be copied
  618. // Returns:
  619. //     TRUE if successful; otherwise returns FALSE
  620. //-----------------------------------------------------------------------
  621. BOOL CopyToClipboard(const CString& strText)
  622. {
  623. if (!OpenClipboard())
  624. return FALSE;
  625. ::EmptyClipboard();
  626. int iLen = (strText.GetLength() + 1) * sizeof(TCHAR);
  627. HGLOBAL hglbCopy = ::GlobalAlloc(GMEM_MOVEABLE, iLen);
  628. if (hglbCopy == NULL)
  629. {
  630. ::CloseClipboard();
  631. return FALSE;
  632. }
  633. LPTSTR lptstrCopy = (TCHAR*)GlobalLock(hglbCopy);
  634. STRCPY_S(lptstrCopy, strText.GetLength() + 1, (LPCTSTR)strText);
  635. GlobalUnlock(hglbCopy);
  636. #ifndef _UNICODE
  637. ::SetClipboardData(CF_TEXT, hglbCopy);
  638. #else
  639. ::SetClipboardData(CF_UNICODETEXT, hglbCopy);
  640. #endif
  641. if (!::CloseClipboard())
  642. return FALSE;
  643. return TRUE;
  644. }
  645. //-----------------------------------------------------------------------
  646. // Summary:
  647. //     Retrieves masked text of the control
  648. // Parameters:
  649. //     nStartPos - Start position
  650. //     nEndPos - End position
  651. // Returns:
  652. //     Masked text of the control.
  653. //-----------------------------------------------------------------------
  654. CString GetMaskedText(int nStartPos = 0, int nEndPos = -1) const
  655. {
  656. if (nEndPos == -1)
  657. nEndPos = m_strWindowText.GetLength();
  658. else
  659. nEndPos = min(nEndPos, m_strWindowText.GetLength());
  660. CString strBuffer;
  661. for (int i = nStartPos; i < nEndPos; ++i)
  662. {
  663. if (IsPromptPos(i))
  664. {
  665. strBuffer += m_strWindowText[i];
  666. }
  667. }
  668. return strBuffer;
  669. }
  670. protected:
  671. //{{AFX_CODEJOCK_PRIVATE
  672. afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  673. {
  674. if (!CanUseMask())
  675. {
  676. TBase::OnKeyDown(nChar, nRepCnt, nFlags); // default processing.
  677. return;
  678. }
  679. BOOL bShift = (::GetKeyState(VK_SHIFT) < 0);
  680. BOOL bCtrl = (::GetKeyState(VK_CONTROL) < 0);
  681. switch (nChar)
  682. {
  683. case VK_UP:
  684. case VK_LEFT:
  685. case VK_HOME:
  686. {
  687. TBase::OnKeyDown(nChar, nRepCnt, nFlags);
  688. GetMaskState(FALSE);
  689. int iStartChar = m_nStartChar;
  690. CorrectPosition(iStartChar, FALSE);
  691. if (m_nStartChar < iStartChar)
  692. {
  693. m_nStartChar = iStartChar;
  694. if (!bShift)
  695. m_nEndChar = iStartChar;
  696. }
  697. SetMaskState();
  698. }
  699. return;
  700. case VK_DOWN:
  701. case VK_RIGHT:
  702. case VK_END:
  703. {
  704. TBase::OnKeyDown(nChar, nRepCnt, nFlags);
  705. GetMaskState(FALSE);
  706. int iEndChar = m_nEndChar;
  707. CorrectPosition(iEndChar);
  708. if (m_nEndChar > iEndChar)
  709. {
  710. m_nEndChar = iEndChar;
  711. if (!bShift)
  712. m_nStartChar = iEndChar;
  713. }
  714. SetMaskState();
  715. }
  716. return;
  717. case VK_INSERT:
  718. {
  719. if (bCtrl)
  720. {
  721. MaskCopy();
  722. }
  723. else if (bShift)
  724. {
  725. MaskPaste();
  726. }
  727. else
  728. {
  729. m_bOverType = !m_bOverType; // set the type-over flag
  730. }
  731. }
  732. return;
  733. case VK_DELETE:
  734. {
  735. GetMaskState();
  736. if (m_nStartChar == m_nEndChar)
  737. {
  738. m_nEndChar = m_nStartChar +1;
  739. }
  740. else if (bShift)
  741. {
  742. MaskCopy();
  743. }
  744. MaskDeleteSel();
  745. SetMaskState();
  746. }
  747. return;
  748. case VK_SPACE:
  749. {
  750. GetMaskState();
  751. if (!PosInRange(m_nStartChar) || !IsPromptPos(m_nStartChar))
  752. {
  753. NotifyPosNotInRange();
  754. return;
  755. }
  756. TCHAR chSpace = _T(' ');
  757. if (!ProcessMask(chSpace, m_nStartChar))
  758. chSpace = m_chPrompt;
  759. ProcessChar(chSpace);
  760. SetMaskState();
  761. }
  762. return;
  763. case VK_BACK:
  764. {
  765. GetMaskState(FALSE);
  766. if ((m_nStartChar > 0) &&
  767. (m_nStartChar <= m_strLiteral.GetLength()))
  768. {
  769. if (m_nStartChar == m_nEndChar)
  770. {
  771. m_nStartChar--;
  772. CorrectPosition(m_nStartChar, FALSE);
  773. if (m_bOverType && PosInRange(m_nStartChar))
  774. {
  775. m_strWindowText.SetAt(m_nStartChar, m_strDefault[m_nStartChar]);
  776. m_nEndChar = m_nStartChar;
  777. }
  778. }
  779. MaskDeleteSel();
  780. SetMaskState();
  781. }
  782. else
  783. {
  784. NotifyPosNotInRange();
  785. }
  786. }
  787. return;
  788. }
  789. TBase::OnKeyDown(nChar, nRepCnt, nFlags);
  790. }
  791. void ProcessChar(TCHAR nChar)
  792. {
  793. int iLen = m_strLiteral.GetLength();
  794. if (m_nStartChar >= iLen)
  795. {
  796. NotifyPosNotInRange();
  797. return;
  798. }
  799. if (m_nStartChar != m_nEndChar)
  800. {
  801. MaskDeleteSel();
  802. }
  803. ASSERT(m_nStartChar == m_nEndChar);
  804. CorrectPosition(m_nStartChar);
  805. if (CanOverType())
  806. {
  807. m_strWindowText.SetAt(m_nStartChar, nChar);
  808. }
  809. else
  810. {
  811. InsertCharAt(m_nStartChar, nChar);
  812. }
  813. if (m_nStartChar < iLen)
  814. m_nStartChar++;
  815. CorrectPosition(m_nStartChar);
  816. m_nEndChar = m_nStartChar;
  817. }
  818. afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  819. {
  820. if (!CanUseMask())
  821. {
  822. TBase::OnChar(nChar, nRepCnt, nFlags);
  823. return;
  824. }
  825. switch (nChar)
  826. {
  827. case VK_UP:
  828. case VK_LEFT:
  829. case VK_DOWN:
  830. case VK_RIGHT:
  831. case VK_HOME:
  832. case VK_END:
  833. case VK_DELETE:
  834. case VK_SPACE:
  835. case VK_BACK:
  836. return; // handled in WM_KEYDOWN
  837. }
  838. GetMaskState();
  839. if (!PosInRange(m_nStartChar) || !IsPromptPos(m_nStartChar))
  840. {
  841. NotifyPosNotInRange();
  842. return;
  843. }
  844. TCHAR ch = (TCHAR)nChar;
  845. if (!CheckChar(ch, m_nStartChar))
  846. {
  847. NotifyInvalidCharacter(ch, m_strMask[m_nStartChar]);
  848. return;
  849. }
  850. if (IsPrintChar(ch))
  851. {
  852. ProcessChar(ch);
  853. SetMaskState(FALSE);
  854. }
  855. else
  856. {
  857. if (nChar != 127)
  858. TBase::OnChar(nChar, nRepCnt, nFlags);
  859. }
  860. }
  861. afx_msg void OnSetFocus(CWnd* pOldWnd)
  862. {
  863. TBase::OnSetFocus(pOldWnd);
  864. if (!CanUseMask())
  865. {
  866. return;
  867. }
  868. MaskGetSel();
  869. CorrectPosition(m_nStartChar);
  870. m_nEndChar = m_nStartChar;
  871. SetSel(m_nStartChar, m_nEndChar);
  872. }
  873. afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI)
  874. {
  875. if (!CanUseMask())
  876. {
  877. pCmdUI->Enable(CanUndo());
  878. }
  879. else
  880. {
  881. pCmdUI->Enable(m_bModified);
  882. }
  883. }
  884. //}}AFX_CODEJOCK_PRIVATE
  885. //{{AFX_CODEJOCK_PRIVATE
  886. // Some goodies
  887. BOOL CorrectPosition(int& iPos, BOOL bForward = TRUE) // used internally
  888. {
  889. int iLen = m_strLiteral.GetLength();
  890. if (IsPromptPos(iPos))
  891. return TRUE;
  892. if (bForward)
  893. {
  894. for (; iPos < iLen; iPos++)
  895. {
  896. if (IsPromptPos(iPos))
  897. return TRUE;
  898. }
  899. for (; iPos >= 0; iPos--)
  900. {
  901. if (IsPromptPos(iPos - 1))
  902. return FALSE;
  903. }
  904. }
  905. else
  906. {
  907. for (; iPos >= 0; iPos--)
  908. {
  909. if (IsPromptPos(iPos))
  910. return TRUE;
  911. }
  912. for (; iPos < iLen; iPos++)
  913. {
  914. if (IsPromptPos(iPos))
  915. return FALSE;
  916. }
  917. }
  918. return FALSE;
  919. }
  920. virtual BOOL IsPrintChar(TCHAR nChar)
  921. {
  922. return _istprint(nChar) || IsAlphaChar(nChar);
  923. }
  924. //-----------------------------------------------------------------------
  925. // Summary:
  926. //     This method determines if nChar is alpha character
  927. // Parameters:
  928. //     nChar - Character need to test
  929. // Returns:
  930. //     TRUE if nChar is alpha character.
  931. //-----------------------------------------------------------------------
  932. virtual BOOL IsAlphaChar(TCHAR nChar)
  933. {
  934. if (_istalpha(nChar))
  935. return TRUE;
  936. if (ConvertUnicodeAlpha(nChar, TRUE) != nChar)
  937. return TRUE;
  938. if (ConvertUnicodeAlpha(nChar, FALSE) != nChar)
  939. return TRUE;
  940. return FALSE;
  941. }
  942. virtual void NotifyPosNotInRange()
  943. {
  944. ::MessageBeep((UINT)-1);
  945. }
  946. virtual void NotifyInvalidCharacter(TCHAR /*nChar*/, TCHAR /*chMask*/)
  947. {
  948. ::MessageBeep((UINT)-1);
  949. }
  950. BOOL IsPromptPos(int nPos) const
  951. {
  952. return IsPromptPos(m_strLiteral, nPos);
  953. }
  954. BOOL IsPromptPos(const CString& strLiteral, int nPos) const
  955. {
  956. return (nPos >= 0 && nPos < strLiteral.GetLength()) && (strLiteral[nPos] == m_chPrompt);
  957. }
  958. void CorrectWindowText()
  959. {
  960. int nLiteralLength = m_strLiteral.GetLength();
  961. int nWindowTextLength = m_strWindowText.GetLength();
  962. if (nWindowTextLength > nLiteralLength)
  963. {
  964. m_strWindowText = m_strWindowText.Left(nLiteralLength);
  965. }
  966. else if (nWindowTextLength < nLiteralLength)
  967. {
  968. m_strWindowText += m_strLiteral.Mid(nWindowTextLength, nLiteralLength - nWindowTextLength);
  969. }
  970. }
  971. void GetMaskState(BOOL bCorrectSelection = TRUE)
  972. {
  973. if (!m_hWnd)
  974. return;
  975. ASSERT(m_bUseMask);
  976. MaskGetSel();
  977. GetWindowText(m_strWindowText);
  978. ASSERT(m_strDefault.GetLength() == m_strLiteral.GetLength());
  979. ASSERT(m_strMask.GetLength() == m_strLiteral.GetLength());
  980. CorrectWindowText();
  981. if (bCorrectSelection)
  982. {
  983. CorrectPosition(m_nStartChar);
  984. CorrectPosition(m_nEndChar);
  985. if (m_nEndChar < m_nStartChar)
  986. m_nEndChar = m_nStartChar;
  987. }
  988. }
  989. void MaskGetSel() // To allow CEdit and CRichEditCtrl
  990. {
  991. if (m_hWnd)
  992. {
  993. SendMessage(EM_GETSEL, (WPARAM)&m_nStartChar, (LPARAM)&m_nEndChar);
  994. }
  995. }
  996. void SetMaskState(BOOL bUpdateUndo = TRUE)
  997. {
  998. if (!m_hWnd)
  999. return;
  1000. ASSERT(m_bUseMask);
  1001. CString strWindowText;
  1002. GetWindowText(strWindowText);
  1003. CorrectWindowText();
  1004. HideCaret();
  1005. if (strWindowText != m_strWindowText)
  1006. {
  1007. SetWindowText(m_strWindowText);
  1008. if (bUpdateUndo || m_bUpdateUndo)
  1009. m_strUndoBuffer = strWindowText;
  1010. m_bRedo = FALSE;
  1011. m_bModified = TRUE;
  1012. }
  1013. m_bUpdateUndo = bUpdateUndo;
  1014. SetSel(m_nStartChar, m_nEndChar);
  1015. ShowCaret();
  1016. }
  1017. //}}AFX_CODEJOCK_PRIVATE
  1018. //-----------------------------------------------------------------------
  1019. // Summary:
  1020. //     The framework calls this member function when the user selects an item from a menu
  1021. // Parameters:
  1022. //     wParam - The low-order word of wParam identifies the command ID of the menu item, control, or accelerator. The high-order word of wParam specifies the notification message if the message is from a control. If the message is from an accelerator, the high-order word is 1. If the message is from a menu, the high-order word is 0
  1023. //     lParam - Identifies the control that sends the message if the message is from a control. Otherwise, lParam is 0.
  1024. // Returns:
  1025. //     An application returns nonzero if it processes this message; otherwise 0.
  1026. //-----------------------------------------------------------------------
  1027. virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam)
  1028. {
  1029. switch (LOWORD(wParam))
  1030. {
  1031. case ID_EDIT_CUT:
  1032. MaskCut();
  1033. return TRUE;
  1034. case ID_EDIT_COPY:
  1035. MaskCopy();
  1036. return TRUE;
  1037. case ID_EDIT_PASTE:
  1038. MaskPaste();
  1039. return TRUE;
  1040. case ID_EDIT_CLEAR:
  1041. MaskClear();
  1042. return TRUE;
  1043. case ID_EDIT_UNDO:
  1044. MaskUndo();
  1045. return TRUE;
  1046. case ID_EDIT_SELECT_ALL:
  1047. MaskSelectAll();
  1048. return TRUE;
  1049. }
  1050. return TBase::OnCommand(wParam, lParam);
  1051. }
  1052. protected:
  1053. int         m_nStartChar;       // Current position of the first character in the current selection.
  1054. int         m_nEndChar;         // Current position of the first non-selected character past the end of the current selection.
  1055. BOOL        m_bUseMask;         // TRUE to use the edit mask.
  1056. BOOL        m_bOverType;        // TRUE to over type the text, set with VK_INSERT key press.
  1057. BOOL        m_bRedo;            // TRUE to redo, or FALSE to undo.
  1058. BOOL        m_bModified;        // TRUE if mask edit has been modified.
  1059. TCHAR       m_chPrompt;         // Prompt character used to identify the text entry.
  1060. CString     m_strMask;          // Buffer that holds the actual edit mask value.
  1061. CString     m_strDefault;       // Contains the edit controls default display text.
  1062. CString     m_strUndoBuffer;    // Holds the contents of the undo buffer.
  1063. CString     m_strRedoBuffer;    // Holds the contents of the redo buffer.
  1064. CString     m_strWindowText;    // Buffer that holds the actual edit text.
  1065. CString     m_strLiteral;       // Literal format that restricts where the user can enter text.
  1066. BOOL        m_bUpdateUndo;      // TRUE to update undo
  1067. };
  1068. //{{AFX_CODEJOCK_PRIVATE
  1069. #define ON_MESSAGE_BOOL(message, memberFxn) 
  1070. { message, 0, 0, 0, AfxSig_bv, 
  1071. (AFX_PMSG)(AFX_PMSGW)(BOOL (AFX_MSG_CALL CWnd::*)(void))&memberFxn },
  1072. #define ON_MASKEDIT_REFLECT
  1073. ON_MESSAGE_BOOL(WM_CUT, MaskCut)
  1074. ON_MESSAGE_BOOL(WM_PASTE, MaskPaste)
  1075. ON_MESSAGE_BOOL(WM_CLEAR, MaskClear)
  1076. ON_MESSAGE_BOOL(WM_UNDO, MaskUndo)
  1077. ON_MESSAGE_BOOL(WM_COPY, MaskCopy)
  1078. ON_WM_KEYDOWN()
  1079. ON_WM_CHAR()
  1080. ON_WM_SETFOCUS
  1081. //}}AFX_CODEJOCK_PRIVATE
  1082. //////////////////////////////////////////////////////////////////////
  1083. #endif // #if !defined(__XTMASKEDITEX_H__)