| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340 |
- #pragma once
- #include <afxpriv.h> // 由于用到了一个未公开的宏ON_MESSAGE_VOID
- // 因此需要包含这个MFC私有的头文件
- //////////////////////////////////////////////////////////////////////
- // Summary:
- // CMaskEditT is a template class. It allows text masking to be
- // applied to the control to format it for special editing restrictions.
- //////////////////////////////////////////////////////////////////////
- template <typename TBase>
- class CMaskEditT : public TBase
- {
- public:
- //-----------------------------------------------------------------------
- // Summary:
- // Constructs a CMaskEditT object
- //-----------------------------------------------------------------------
- CMaskEditT()
- : m_bOverType( TRUE )
- , m_bUseMask( TRUE )
- , m_bModified( FALSE )
- , m_strWindowText( _T( "" ) )
- , m_strMask( _T( "" ) )
- , m_strLiteral( _T( "" ) )
- , m_strDefault( _T( "" ) )
- , m_chPrompt( _T('_') )
- {
- }
- public:
- //-----------------------------------------------------------------------
- // Parameters:
- // bUseMask - TRUE to enable the mask. FALSE to disable the mask.
- // Summary:
- // Call this member function to enable or disable the mask for the mask
- // edit control.
- //-----------------------------------------------------------------------
- void SetUseMask(BOOL bUseMask) {
- m_bUseMask = bUseMask;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to determine if the mask for the edit
- // control can be used.
- // Returns:
- // TRUE if the mask can be used, otherwise returns FALSE.
- //-----------------------------------------------------------------------
- BOOL CanUseMask() {
- return m_bUseMask && ((GetStyle() & ES_READONLY) == 0);
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to enable or disable type over, also
- // known as insert mode.
- // Parameters:
- // bOverType - TRUE to enable type over.
- //-----------------------------------------------------------------------
- void SetOverType(BOOL bOverType) {
- m_bOverType = bOverType;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to determine if type over has been enabled.
- // Returns:
- // TRUE if type over is enabled, otherwise returns FALSE.
- //-----------------------------------------------------------------------
- BOOL CanOverType() {
- return m_bOverType;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to determine if the index specified
- // by 'iPos' is a valid index for the currently displayed edit text.
- // Parameters:
- // iPos - Index of the character to check.
- // Returns:
- // TRUE if the index is valid, otherwise returns FALSE.
- //-----------------------------------------------------------------------
- BOOL PosInRange(int iPos) {
- return ( ( iPos >= 0 ) && ( iPos < m_strLiteral.GetLength( ) ) );
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function retrieves the character that is currently used as
- // the mask prompt. The mask prompt indicates that the field is editable.
- // Returns:
- // A TCHAR data type.
- //-----------------------------------------------------------------------
- TCHAR GetPromptChar() {
- return m_chPrompt;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to set the prompt character that is
- // displayed to the user that indicates the field can be edited.
- // Parameters:
- // ch - A TCHAR data type.
- //-----------------------------------------------------------------------
- void SetPromptChar(TCHAR ch)
- {
- if (m_chPrompt == ch)
- return;
- for (int i = 0; i < m_strLiteral.GetLength(); i++)
- if (m_strLiteral[i] == m_chPrompt) m_strLiteral.SetAt(i, ch);
- for (int j = 0; j < m_strWindowText.GetLength(); j++)
- if (m_strWindowText[j] == m_chPrompt) m_strWindowText.SetAt(j, ch);
- // 原来的代码没有修改m_strDefault,导致它仍然使用旧的提示字符。
- // 如果用户在改变提示字符后使用回退键删除字符,被删除位置出现
- // 的是旧的提示字符。因此对m_strDefault也要进行修改。
- for (int k = 0; k < m_strDefault.GetLength(); k++)
- if (m_strDefault[k] == m_chPrompt) m_strDefault.SetAt(k, ch);
- m_chPrompt = ch;
- SetWindowText( m_strWindowText );
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to perform a cut operation using the
- // currently selected text.
- //-----------------------------------------------------------------------
- void MaskCut()
- {
- if ( !CanUseMask( ))
- {
- DefWindowProc( WM_CUT, 0, 0);
- }
- else
- {
- MaskCopy( );
- MaskClear( );
- }
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to perform a copy operation using the
- // currently selected text.
- //-----------------------------------------------------------------------
- void MaskCopy()
- {
- if ( !CanUseMask( ))
- {
- DefWindowProc( WM_COPY, 0, 0);
- }
- else
- {
- int nStartChar, nEndChar;
- GetSel( nStartChar, nEndChar );
- if (nStartChar == nEndChar)
- return;
- CString strBuffer;
- int i;
- for ( i = nStartChar; i < nEndChar; ++i )
- {
- if ( m_strLiteral.GetAt( i ) == m_chPrompt )
- {
- if ( m_strWindowText.GetAt( i ) == m_chPrompt )
- continue;
- strBuffer += m_strWindowText.GetAt( i );
- }
- }
- CopyToClipboard( strBuffer );
- }
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to perform a paste operation using the
- // current clipboard text.
- //-----------------------------------------------------------------------
- void MaskPaste()
- {
- if ( !CanUseMask( ))
- {
- DefWindowProc(WM_PASTE, 0, 0);
- }
- else
- {
- if ( !OpenClipboard( ) )
- return;
- // 原来的代码在处理UNICODE时是错误的,改进如下
- #ifdef _UNICODE
- HGLOBAL hglbPaste = ::GetClipboardData( CF_UNICODETEXT );
- #else
- HGLOBAL hglbPaste = ::GetClipboardData( CF_TEXT );
- #endif
- if (hglbPaste == NULL)
- {
- ::CloseClipboard();
- return;
- }
- CString strPaste = (TCHAR*)::GlobalLock(hglbPaste);
- ::GlobalUnlock( hglbPaste );
- ::CloseClipboard();
- MaskClear( );
- if (strPaste.IsEmpty())
- return;
- // 原来的代码有两个Bug:
- // 1 如果碰到插入位置是固定字符,会导致文本顺序出现混乱。
- // 2 完成粘贴操作后,插入光标没有设置到新文本的后面。
- // 改进如下
- int nStartChar, nEndChar;
- GetSel(nStartChar, nEndChar);
- for (int i = 0; i < strPaste.GetLength(); i++)
- {
- if ( !CorrectPosition(nStartChar, TRUE, FALSE) )
- break;
- UINT ch = strPaste[i];
- if (CheckChar(nStartChar, ch, FALSE))
- {
- InsertCharAt( nStartChar, ( TCHAR )ch );
- nStartChar++;
- }
- }
- m_bModified = TRUE;
- SetWindowText( m_strWindowText );
- if ( nStartChar < m_strLiteral.GetLength() )
- CorrectPosition( nStartChar, TRUE, FALSE );
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- }
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to clear the current text selection.
- //-----------------------------------------------------------------------
- void MaskClear()
- {
- if ( !CanUseMask( ))
- {
- DefWindowProc( WM_CLEAR, 0, 0);
- }
- else
- {
- int nStartChar, nEndChar;
- GetSel(nStartChar, nEndChar);
- if ( nStartChar == nEndChar )
- return;
- // check to see if there is anything left to delete
- int iLength = m_strWindowText.GetLength( );
- int i;
- for ( i = nStartChar; i < iLength; ++i )
- {
- TCHAR ch1 = m_strLiteral.GetAt( i );
- TCHAR ch2 = m_strWindowText.GetAt( i );
- if ( ( ch1 == m_chPrompt ) && ( ch2 != m_chPrompt ) )
- {
- break;
- }
- }
- if ( i == iLength )
- {
- // 没有可删除的内容,都是提示字符或固定字符
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- return;
- }
- // 原来的代码没有考虑到被选中文本以固定字符开头的情况,此时调用
- // DeleteCharAt没有效果,因此要先找出被选中文本第一个可编辑字符
- // 的位置,然后在该位置上调用DeleteCharAt
- int iPos = nStartChar;
- if (!CorrectPosition(iPos))
- return;
- if (iPos >= nEndChar)
- {
- // 被选中的文本都是固定字符
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- return;
- }
- nStartChar = iPos;
- for ( i = nStartChar; i < nEndChar; ++i )
- {
- if ( m_strLiteral.GetAt( i ) == m_chPrompt )
- {
- DeleteCharAt( nStartChar );
- }
- }
- m_bModified = TRUE;
- SetWindowText( m_strWindowText );
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- }
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to undo the previous action.
- //-----------------------------------------------------------------------
- void MaskUndo()
- {
- if ( !CanUseMask( ))
- {
- DefWindowProc( EM_UNDO, 0, 0);
- }
- else
- {
- // 如果采用格式化输入,不支持Undo功能
- :: MessageBeep( ( UINT )-1 );
- }
- }
- //-----------------------------------------------------------------------
- // 用途:
- // 控件消息EM_CANUNDO的处理函数
- //-----------------------------------------------------------------------
- afx_msg LRESULT MaskCanUndo(WPARAM wParam, LPARAM lParam)
- {
- if ( !CanUseMask( ))
- {
- return DefWindowProc( EM_CANUNDO, wParam, wParam);
- }
- else
- {
- return FALSE; // 如果采用格式化输入,不能Undo
- }
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is called to select all text in the mask edit
- // control.
- //-----------------------------------------------------------------------
- void MaskSelectAll()
- {
- if ( !CanUseMask( ))
- {
- SetSel(0, -1);
- }
- else
- {
- // 原来的代码在选择全部文本时,跳过起始的固定字符。
- // 我觉得还是用缺省的功能更好一些。
- SetSel(0, -1);
- }
- }
- //-----------------------------------------------------------------------}
- // Summary:
- // This member function is called to determine if the text has been modified.
- // Returns:
- // TRUE if the text has changed, otherwise returns FALSE.
- //-----------------------------------------------------------------------
- BOOL IsModified() {
- return m_bModified;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This method called to set masked text for the edit control.
- // Parameters:
- // lpszMaskedText - Text string without mask.
- // Remarks:
- // If a mask is used, then the mask will be applied to the text
- // in lpszMaskedText.
- //-----------------------------------------------------------------------
- void SetMaskedText(LPCTSTR lpszMaskedText)
- {
- CString strMaskedText = lpszMaskedText;
- int nLen = strMaskedText.GetLength();
- int x = 0;
- m_strWindowText = m_strLiteral;
- for (int i = 0; (i < m_strWindowText.GetLength()) && (x < nLen); i++)
- {
- if (strMaskedText[x] == m_strWindowText[i])
- {
- x ++;
- } else if (m_strWindowText[i] == m_chPrompt)
- {
- m_strWindowText.SetAt(i, strMaskedText[x]);
- x ++;
- }
- }
- // set the window text for the control.
- m_bModified = FALSE;
- SetWindowText( m_strWindowText );
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function will set the mask for the edit control.
- // Parameters:
- // lpszMask - The format for the mask field. For example, if you wanted to set
- // the mask for a phone number, and you only wanted digits to be entered,
- // your mask might look like this; _T("(000) 000-0000").
- // lpszLiteral - The literal format is entered here. Wherever you place an underscore
- // ('_') is where the user will be allowed to enter data only. Using
- // the phone number example; _T("(___) ___-____").
- // lpszDefault - Text that is to be displayed when the control is initialized. For
- // example; _T("(800) 555-1212"). If NULL, 'lpszLiteral' is used to initialize
- // the edit text.
- // Remarks:
- // The values that can be set are:
- // Mask Character Description
- // --------------------- ------------------------
- // 0 Numeric (0-9)
- // 9 Numeric (0-9) or space (' ')
- // # Numeric (0-9) or space (' ') or ('+') or ('-')
- // L Alpha (a-Z)
- // ? Alpha (a-Z) or space (' ')
- // A Alpha numeric (0-9 and a-Z)
- // a Alpha numeric (0-9 and a-Z) or space (' ')
- // & All print character only
- // H Hex digit (0-9 and A-F)
- // X Hex digit (0-9 and A-F) and space (' ')
- // > Forces characters to upper case (A-Z)
- // < Forces characters to lower case (a-z)
- //-----------------------------------------------------------------------
- virtual void SetEditMask(LPCTSTR lpszMask,LPCTSTR lpszLiteral,LPCTSTR lpszDefault=NULL)
- {
- ASSERT(lpszMask);
- ASSERT(lpszLiteral);
- // initialize the mask for the control.
- m_strMask = lpszMask;
- m_strLiteral = lpszLiteral;
- ASSERT(m_strMask.GetLength() == m_strLiteral.GetLength());
- if ( lpszDefault == NULL )
- {
- m_strWindowText = lpszLiteral;
- m_strDefault = lpszLiteral;
- }
- else
- {
- SetMaskedText(lpszDefault);
- m_strDefault = m_strWindowText;
- }
- ASSERT(m_strWindowText.GetLength() == m_strLiteral.GetLength());
- // set the window text for the control.
- m_bModified = FALSE;
- SetWindowText( m_strWindowText );
- }
- //-----------------------------------------------------------------------
- // Summary:
- // Converts character to Upper/Lower case.
- // Parameters:
- // nChar - Char to be converted
- // bUpperCase - TRUE to convert to upper case
- // Returns:
- // Converted character.
- //-----------------------------------------------------------------------
- TCHAR ConvertUnicodeAlpha(TCHAR nChar, BOOL bUpperCase)
- {
- CString strTemp(nChar);
- if (bUpperCase) strTemp.MakeUpper(); else strTemp.MakeLower();
- return strTemp[0];
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This method determines if nChar is alpha character
- // Parameters:
- // nChar - Character need to test
- // Returns:
- // TRUE if nChar is alpha character.
- //-----------------------------------------------------------------------
- BOOL IsUnicodeAlpha(TCHAR nChar)
- {
- if (ConvertUnicodeAlpha(nChar, TRUE) != nChar)
- return TRUE;
- if (ConvertUnicodeAlpha(nChar, FALSE) != nChar)
- return TRUE;
- return FALSE;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is used internally to validate the character indicated
- // by 'nChar'.
- // Parameters:
- // iPos - 字符位置
- // nChar - Contains the character code value of the key.
- // bBeep - TRUE to enable beep. FALSE to disable beep.
- // Returns:
- // TRUE if successful, otherwise returns FALSE.
- //-----------------------------------------------------------------------
- virtual BOOL CheckChar(int iPos, UINT& nChar, BOOL bBeep=TRUE)
- {
- // do not use mask
- if ( !CanUseMask( ) )
- {
- return FALSE;
- }
- // control character, OK
- if ( !_istprint( ( TCHAR )nChar ) && !IsUnicodeAlpha(( TCHAR )nChar))
- {
- // 原来的程序在这里返回TRUE,根据对上下文的理解,
- // 应该返回FALSE,并且发出提示音
- if ( bBeep )
- ::MessageBeep( (UINT)-1 );
- return FALSE;
- }
- // advance to the first character input position.
- int i = 0;
- for ( i = iPos; i < m_strLiteral.GetLength( ); ++i )
- {
- if ( m_strLiteral.GetAt( i ) == m_chPrompt )
- break;
- }
- // make sure the string is not longer than the mask
- if ( i >= m_strMask.GetLength( ) )
- {
- if ( bBeep )
- {
- :: MessageBeep( ( UINT )-1 );
- }
- return FALSE;
- }
- if ( !ProcessMask( nChar, i ) )
- {
- if ( bBeep )
- {
- :: MessageBeep( ( UINT )-1 );
- }
- return FALSE;
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // This member function is used internally to process the character passed
- // in by 'nChar' whose index is specified by 'nEndPos'.
- // Parameters:
- // nChar - Contains the character code value of the key.
- // nEndPos - Index of character in display string.
- // Returns:
- // TRUE if successful, otherwise returns FALSE.
- //-----------------------------------------------------------------------
- virtual BOOL ProcessMask(UINT& nChar,int nEndPos)
- {
- // check the key against the mask
- switch ( m_strMask.GetAt( nEndPos ) )
- {
- case '0': // digit only //completely changed this
- {
- if ( _istdigit( ( TCHAR )nChar ) ) {
- return TRUE;
- }
- break;
- }
- case '9': // digit or space
- {
- if ( _istdigit( ( TCHAR )nChar ) ) {
- return TRUE;
- }
- if ( nChar == ' ' ) {
- return TRUE;
- }
- break;
- }
- case '#': // digit or space or '+' or '-'
- {
- if ( _istdigit( ( TCHAR )nChar ) ) {
- return TRUE;
- }
- if ( nChar == ' ' || nChar == '-' || nChar == '+' ) {
- return TRUE;
- }
- break;
- }
- case 'd': // decimal
- {
- if ( _istdigit( ( TCHAR )nChar ) ) {
- return TRUE;
- }
- if ( nChar == ' ' || nChar == '-' || nChar == '+' || nChar == '.' || nChar == ',') {
- return TRUE;
- }
- break;
- }
- case 'L': // alpha only
- {
- if ( _istalpha( ( TCHAR )nChar ) || IsUnicodeAlpha(( TCHAR )nChar) ) {
- return TRUE;
- }
- break;
- }
- case '?': // alpha or space
- {
- if ( _istalpha( ( TCHAR )nChar ) || IsUnicodeAlpha(( TCHAR )nChar) ) {
- return TRUE;
- }
- if ( nChar == ' ' ) {
- return TRUE;
- }
- break;
- }
- case 'A': // alpha numeric only
- {
- if ( _istalnum( ( TCHAR )nChar ) || IsUnicodeAlpha(( TCHAR )nChar)) {
- return TRUE;
- }
- break;
- }
- case 'a': // alpha numeric or space
- {
- if ( _istalnum( ( TCHAR )nChar ) || IsUnicodeAlpha(( TCHAR )nChar)) {
- return TRUE;
- }
- if ( nChar == ' ' ) {
- return TRUE;
- }
- break;
- }
- case '&': // all print character only
- {
- if ( _istprint( ( TCHAR )nChar ) || IsUnicodeAlpha(( TCHAR )nChar) ) {
- return TRUE;
- }
- break;
- }
- case 'H': // hex digit
- {
- if ( _istxdigit( ( TCHAR )nChar ) ) {
- return TRUE;
- }
- break;
- }
- case 'X': // hex digit or space
- {
- if ( _istxdigit( ( TCHAR )nChar ) ) {
- return TRUE;
- }
- if ( nChar == ' ' ) {
- return TRUE;
- }
- break;
- }
- case '>':
- {
- if ( _istalpha( ( TCHAR )nChar ) || IsUnicodeAlpha(( TCHAR )nChar))
- {
- nChar = ConvertUnicodeAlpha( ( TCHAR )nChar, TRUE);
- return TRUE;
- }
- break;
- }
- case '<':
- {
- if ( _istalpha( ( TCHAR )nChar ) || IsUnicodeAlpha(( TCHAR )nChar))
- {
- nChar = ConvertUnicodeAlpha( ( TCHAR )nChar, FALSE);
- return TRUE;
- }
- break;
- }
- }
- return FALSE;
- }
- public:
- //-----------------------------------------------------------------------
- // Summary:
- // Used by class CWinApp to translate window messages before they are dispatched to theTranslateMessage andDispatchMessage Windows functions.
- // Parameters:
- // pMsg - Points to a MSG structure that contains the message to process.
- // Returns:
- // Nonzero if the message was translated and should not be dispatched; 0 if the message was not translated and should be dispatched.
- //-----------------------------------------------------------------------
- virtual BOOL PreTranslateMessage(MSG* pMsg)
- {
- if (!CanUseMask())
- {
- return TBase::PreTranslateMessage(pMsg);
- }
- // intercept Ctrl+C (copy), Ctrl+V (paste), Ctrl+X (cut) and Ctrl+Z (undo)
- // before base class gets a hold of them.
- if ( pMsg->message == WM_KEYDOWN )
- {
- // 原来的代码在这里处理按键为 + 和 - 的情况,
- // 我觉得还是由WM_CHAR消息来处理更合适一些
- if ( ::GetKeyState( VK_CONTROL ) < 0 )
- {
- switch ( pMsg->wParam )
- {
- case 'X':
- {
- MaskCut( );
- return TRUE;
- }
- case 'C':
- {
- MaskCopy( );
- return TRUE;
- }
- case 'V':
- {
- MaskPaste( );
- return TRUE;
- }
- case 'Z':
- {
- MaskUndo( );
- return TRUE;
- }
- }
- }
- }
- return TBase::PreTranslateMessage(pMsg);
- }
- //-----------------------------------------------------------------------
- // 用途:
- // 由指定位置开始搜索并返回第一个可编辑的位置。
- // 参数:
- // iPos - 指定起始位置,如果搜索成功,返回搜索到的位置。
- // bForward - 标识搜索方向是往前(TRUE)还是往回(FALSE)。
- // bBeep - 标识在调用失败时是否发出提示音。
- // 返回值:
- // 搜索成功返回TRUE,否则返回FALSE。
- //-----------------------------------------------------------------------
- virtual BOOL CorrectPosition(int& iPos, BOOL bForward=TRUE, BOOL bBeep=TRUE) // used internally
- {
- int iLen = m_strWindowText.GetLength( );
- if ( iPos == iLen )
- {
- if ( bBeep )
- {
- ::MessageBeep( ( UINT )-1 );
- }
- return FALSE;
- }
- if (! PosInRange(iPos))
- return FALSE;
- if ( m_strLiteral.GetAt( iPos ) != m_chPrompt )
- {
- int i;
- if ( bForward )
- {
- for ( i = iPos; i < iLen; ++i )
- {
- if ( m_strLiteral.GetAt( i ) == m_chPrompt )
- {
- iPos = i;
- break;
- }
- }
- if ( i == iLen )
- {
- if ( bBeep )
- {
- ::MessageBeep( ( UINT )-1 );
- }
- return FALSE;
- }
- }
- else
- {
- for ( i = iPos; i >= 0; --i )
- {
- if ( m_strLiteral.GetAt( i ) == m_chPrompt )
- {
- iPos = i;
- break;
- }
- }
- if ( i == -1 )
- {
- iPos++;
- if ( bBeep )
- {
- ::MessageBeep( ( UINT )-1 );
- }
- return FALSE;
- }
- }
- }
- return TRUE;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // Deletes character in specified position
- // Parameters:
- // iPos - Position for character to be deleted.
- //-----------------------------------------------------------------------
- virtual void DeleteCharAt(int iPos)
- {
- if (!PosInRange(iPos))
- return;
- CString strBuffer = GetMaskedText( iPos+1 );
- strBuffer += m_chPrompt;
- int x = 0;
- int iLen = strBuffer.GetLength( );
- int i;
- for (i = iPos; i < m_strLiteral.GetLength( ); ++i )
- {
- if ( ( m_strLiteral.GetAt( i ) == m_chPrompt ) )
- {
- m_strWindowText.SetAt( i, strBuffer.GetAt( x ) );
- ++x;
- if ( x == iLen )
- break;
- }
- }
- }
- //-----------------------------------------------------------------------
- // Summary:
- // Inserts character to specified position.
- // Parameters:
- // iPos - Position to insert
- // nChar - Character to be inserted
- //-----------------------------------------------------------------------
- virtual void InsertCharAt(int iPos, TCHAR nChar)
- {
- if (!PosInRange(iPos))
- {
- return;
- }
- UINT uChar = nChar;
- if ( !CheckChar( iPos, uChar, FALSE ) )
- {
- return;
- }
- CString strBuffer = GetMaskedText( iPos );
- CString strTemp(nChar);
- int i, x = 0, iLen = strBuffer.GetLength( );
- for ( i = 1; i < strBuffer.GetLength(); i++ )
- {
- strTemp += strBuffer.GetAt( i-1 );
- }
- strBuffer = strTemp;
- for ( i = iPos; i < m_strWindowText.GetLength( ); i++ )
- {
- if ( m_strLiteral.GetAt( i ) == m_chPrompt )
- {
- m_strWindowText.SetAt( i, strBuffer[ x ] );
- x++;
- if ( x == iLen )
- break;
- }
- }
- }
- //-----------------------------------------------------------------------
- // 用途:
- // 在指定位置插入提示字符。
- // 参数:
- // iPos - 插入位置,要求必须是有效输入位置
- //-----------------------------------------------------------------------
- void InsertPromptCharAt(int iPos)
- {
- ASSERT(m_strLiteral.GetAt(iPos) == m_chPrompt);
- CString strBuffer = GetMaskedText( iPos );
- CString strTemp;
- int i;
- for ( i = 1; i < strBuffer.GetLength(); i++ )
- {
- strTemp += strBuffer.GetAt( i-1 );
- }
- strBuffer = strTemp;
- m_strWindowText.SetAt(iPos, m_chPrompt);
- int x = 0, iLen = strBuffer.GetLength();
- for ( i = iPos+1; i < m_strWindowText.GetLength( ); i++ )
- {
- if ( m_strLiteral.GetAt( i ) == m_chPrompt )
- {
- m_strWindowText.SetAt( i, strBuffer[ x ] );
- x++;
- if ( x == iLen )
- break;
- }
- }
- }
- //-----------------------------------------------------------------------
- // Summary:
- // Copies text to system clipboard
- // Parameters:
- // lpszText - Text to be copied
- // Returns:
- // TRUE if successful; otherwise returns FALSE
- //-----------------------------------------------------------------------
- virtual BOOL CopyToClipboard(LPCTSTR lpszText)
- {
- if ( !OpenClipboard( ) )
- return FALSE;
- ::EmptyClipboard( );
- int iLen = (int)_tcslen( lpszText ) + 1;
- // 原来的代码在处理UNICODE时是错误的,改进如下
- HGLOBAL hglbCopy = ::GlobalAlloc( GMEM_MOVEABLE, iLen*sizeof(TCHAR) );
- if ( hglbCopy == NULL )
- {
- ::CloseClipboard( );
- return FALSE;
- }
- LPTSTR lptstrCopy = ( TCHAR* )::GlobalLock( hglbCopy );
- memcpy(lptstrCopy, lpszText, iLen*sizeof(TCHAR));
- ::GlobalUnlock( hglbCopy );
- #ifdef _UNICODE
- ::SetClipboardData( CF_UNICODETEXT, hglbCopy );
- #else
- ::SetClipboardData( CF_TEXT, hglbCopy );
- #endif
- if ( !::CloseClipboard( ) )
- return FALSE;
- return TRUE;
- }
- //-----------------------------------------------------------------------
- // Summary:
- // Retrieves masked text of the control
- // Parameters:
- // iPos - Start position
- // Returns:
- // Masked text of the control.
- //-----------------------------------------------------------------------
- virtual CString GetMaskedText(int iPos = 0)
- {
- int iWndLen = m_strWindowText.GetLength( );
- ASSERT( iWndLen == m_strLiteral.GetLength( ) ); // must be equal in length
- CString strBuffer;
- int i;
- for ( i = iPos; i < iWndLen; ++i )
- {
- if ( m_strLiteral.GetAt( i ) == m_chPrompt )
- {
- strBuffer += m_strWindowText.GetAt( i );
- }
- }
- return strBuffer;
- }
- protected:
- //{{AFX_MASKEDIT_PRIVATE
- // 消息WM_SETTEXT的处理函数,目的是保证成员变量m_strWindowText和控件文本的一致性
- afx_msg LRESULT OnSetText(WPARAM wParam, LPARAM lParam)
- {
- LRESULT result = DefWindowProc(WM_SETTEXT, wParam, lParam);
- if ( !CanUseMask() )
- return result;
- if ( result && (LPCTSTR)m_strWindowText != (LPCTSTR)lParam )
- // 如果引发消息的语句为SetWindowText(m_strWindowText),则无需处理
- m_strWindowText = (LPCTSTR)lParam;
- return result;
- }
- afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- if (!CanUseMask())
- {
- TBase::OnKeyDown( nChar, nRepCnt, nFlags ); // default processing.
- return;
- }
- int nStartChar, nEndChar;
- GetSel(nStartChar, nEndChar);
- if ( m_strMask.IsEmpty( ) )
- {
- TBase::OnKeyDown( nChar, nRepCnt, nFlags ); // default processing.
- return;
- }
- BOOL bShift = (::GetKeyState(VK_SHIFT) < 0);
- switch ( nChar )
- {
- // 原来的代码在处理光标键及Home、End键时,要跳过固定字符。
- // 我觉得用缺省功能更好一些,VB6的MaskEdit控件用的也是缺省功能
- case VK_INSERT:
- {
- if ( bShift )
- {
- MaskPaste( );
- }
- else
- {
- m_bOverType = !m_bOverType; // set the type-over flag
- }
- }
- return;
- case VK_DELETE:
- {
- if ( nStartChar == nEndChar )
- {
- if ( CorrectPosition( nStartChar ) )
- {
- DeleteCharAt( nStartChar );
- m_bModified = TRUE;
- SetWindowText( m_strWindowText );
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- }
- }
- else
- {
- MaskClear( );
- }
- }
- return;
- case VK_SPACE:
- {
- int iPos = nStartChar;
- if ( CorrectPosition( iPos ) )
- {
- if ( ProcessMask( nChar, iPos ) )
- {
- // 空格为有效字符
- if ( nStartChar != nEndChar )
- {
- // 当前有文本被选中,无论控件处于插入还是
- // 覆写状态,均先删除被选文本,再插入空格
- MaskClear();
- InsertCharAt( iPos, ' ' );
- }
- else
- {
- // 没有文本被选中,则根据状态决定是插入还是覆写空格
- if ( CanOverType( ) )
- m_strWindowText.SetAt( iPos, ' ' );
- else
- InsertCharAt( iPos, ' ' );
- }
- }
- else
- {
- // 空格不是有效字符,则在当前位置输入一个提示字符
- if ( nStartChar != nEndChar )
- {
- // 当前有文本被选中
- // 如果选中的都是固定字符,则发出错误提示音并返回
- if (iPos >= nEndChar)
- {
- ::MessageBeep( ( UINT )-1 );
- return;
- }
- // 删除被选文本
- MaskClear();
- // 插入一个提示字符
- InsertPromptCharAt(iPos);
- }
- else
- {
- // 没有文本被选中,则根据状态决定是插入还是覆写提示字符
- if ( CanOverType( ) )
- m_strWindowText.SetAt( iPos, m_chPrompt );
- else
- InsertPromptCharAt(iPos);
- }
- }
- m_bModified = TRUE;
- SetWindowText( m_strWindowText );
- nStartChar = iPos + 1;
- if ( nStartChar < m_strLiteral.GetLength() )
- CorrectPosition( nStartChar, TRUE, FALSE );
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- }
- }
- return;
- case VK_BACK:
- {
- // 如果有字符被选中,则执行Clear操作,即相当于按了Del键
- if (nStartChar != nEndChar)
- {
- MaskClear();
- return;
- }
- if ( nStartChar > 0 && nStartChar <= m_strLiteral.GetLength( ) )
- {
- nStartChar--;
- if ( CorrectPosition( nStartChar, FALSE ) )
- {
- TCHAR ch = m_chPrompt;
- // get the masked literal representation.
- if ( !m_strDefault.IsEmpty( ) )
- {
- ch = m_strDefault.GetAt( nStartChar );
- }
- m_strWindowText.SetAt( nStartChar, ch );
- m_bModified = TRUE;
- SetWindowText( m_strWindowText );
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- }
- }
- else
- {
- ::MessageBeep( ( UINT )-1 );
- }
- }
- return;
- }
- TBase::OnKeyDown( nChar, nRepCnt, nFlags );
- }
- afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- if (!CanUseMask())
- {
- TBase::OnChar(nChar, nRepCnt, nFlags);
- return;
- }
- switch ( nChar )
- {
- case ' ' : // 空格
- case '\b': // 回退键
- return; // 上述字符已经在消息WM_KEYDOWN中得到了处理
- }
- int nStartChar, nEndChar;
- GetSel(nStartChar, nEndChar);
- if (!CheckChar(nStartChar, nChar))
- {
- return;
- }
- if ( nStartChar != nEndChar )
- {
- // 输入字符时有文本被选中,无论当前处于插入还是
- // 覆写状态,均先删除被选文本,再插入新字符
- MaskClear();
- if ( CorrectPosition(nStartChar) )
- InsertCharAt( nStartChar, ( TCHAR )nChar );
- }
- else
- {
- // 没有文本被选中,则根据状态决定是插入还是覆写
- if ( CorrectPosition(nStartChar) )
- {
- if ( CanOverType( ) )
- m_strWindowText.SetAt( nStartChar, ( TCHAR )nChar );
- else
- InsertCharAt( nStartChar, ( TCHAR )nChar );
- }
- }
- m_bModified = TRUE;
- SetWindowText( m_strWindowText );
- nStartChar++;
- if ( nStartChar < m_strLiteral.GetLength() )
- CorrectPosition( nStartChar, TRUE, FALSE );
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- }
- afx_msg void OnSetFocus(CWnd* pOldWnd)
- {
- TBase::OnSetFocus(pOldWnd);
- if (!CanUseMask())
- {
- return;
- }
- int nStartChar, nEndChar;
- GetSel(nStartChar, nEndChar);
- CorrectPosition( nStartChar, TRUE, FALSE );
- nEndChar = nStartChar;
- SetSel( nStartChar, nEndChar );
- }
- afx_msg void OnUpdateEditUndo(CCmdUI* pCmdUI)
- {
- if (!CanUseMask())
- {
- pCmdUI->Enable( CanUndo( ) );
- }
- else
- {
- pCmdUI->Enable( FALSE );
- }
- }
- //}}AFX_MASKEDIT_PRIVATE
- //-----------------------------------------------------------------------
- // Summary:
- // The framework calls this member function when the user selects an item from a menu
- // Parameters:
- // 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
- // lParam - Identifies the control that sends the message if the message is from a control. Otherwise, lParam is 0.
- // Returns:
- // An application returns nonzero if it processes this message; otherwise 0.
- //-----------------------------------------------------------------------
- virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam)
- {
- switch (LOWORD(wParam))
- {
- case ID_EDIT_CUT:
- if ( !CanUseMask( )) TBase::Cut(); else MaskCut( );
- return TRUE;
- case ID_EDIT_COPY:
- if ( !CanUseMask( )) TBase::Copy(); else MaskCopy( );
- return TRUE;
- case ID_EDIT_PASTE:
- if ( !CanUseMask()) TBase::Paste(); else MaskPaste( );
- return TRUE;
- case ID_EDIT_CLEAR:
- if ( !CanUseMask()) TBase::Clear(); else MaskClear( );
- return TRUE;
- case ID_EDIT_UNDO:
- if ( !CanUseMask()) TBase::Undo(); else MaskUndo( );
- return TRUE;
- case ID_EDIT_SELECT_ALL:
- MaskSelectAll( );
- return TRUE;
- }
- return TBase::OnCommand(wParam, lParam);
- }
- protected:
- BOOL m_bUseMask; // TRUE to use the edit mask.
- BOOL m_bOverType; // TRUE to over type the text, set with VK_INSERT key press.
- BOOL m_bModified; // TRUE if mask edit has been modified.
- TCHAR m_chPrompt; // Prompt character used to identify the text entry.
- CString m_strMask; // Buffer that holds the actual edit mask value.
- CString m_strDefault; // Contains the edit controls default display text.
- CString m_strWindowText; // Buffer that holds the actual edit text.
- CString m_strLiteral; // Literal format that restricts where the user can enter text.
- };
- //{{AFX_MASKEDIT_PRIVATE
- #define ON_MASKEDIT_REFLECT\
- ON_MESSAGE_VOID(WM_CUT, MaskCut)\
- ON_MESSAGE_VOID(WM_PASTE, MaskPaste)\
- ON_MESSAGE_VOID(WM_CLEAR, MaskClear)\
- ON_MESSAGE_VOID(WM_UNDO, MaskUndo)\
- ON_MESSAGE_VOID(EM_UNDO, MaskUndo)\
- ON_MESSAGE(EM_CANUNDO, MaskCanUndo)\
- ON_MESSAGE_VOID(WM_COPY, MaskCopy)\
- ON_MESSAGE(WM_SETTEXT, OnSetText)\
- ON_WM_KEYDOWN()\
- ON_WM_CHAR()\
- ON_WM_SETFOCUS\
- //}}AFX_MASKEDIT_PRIVATE
|