00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "stdafx.h"
00020
00021 #include <cfl/ControlFilterEdit.h>
00022
00023 IMPLEMENT_DYNAMIC( CFilterEdit, CEdit )
00024
00025
00026
00027
00028
00029 CFilterEdit::~CFilterEdit()
00030 {
00031 ;
00032 }
00033
00034
00035
00036
00037
00038 CFilterEdit::CFilterEdit( const bool bProcessChars ) :
00039 m_bProcessChars( bProcessChars ),
00040 m_bAutoValidate( true ),
00041 m_bModal ( true ),
00042 m_bShowInvalid ( true ),
00043 m_bSetBkOnError( false ),
00044 m_bWavyLineOnError ( true ),
00045 m_bBeepOnInvalid( true ),
00046 m_bValid ( true ),
00047 m_bCharValid ( false ),
00048 m_bControlDown ( false ),
00049 m_crFgOK ( RGB ( 0, 0, 0 ) ),
00050 m_crBkOK ( RGB (255, 255, 255 ) ),
00051 m_crFgError ( RGB (255, 255, 255 ) ),
00052 m_crBkError ( RGB (255, 0 , 0 ) )
00053 {
00054 m_brOK.CreateSolidBrush ( m_crBkOK );
00055 m_brError.CreateSolidBrush( m_crBkError );
00056 }
00057
00058
00059
00060
00061
00062 void CFilterEdit::SetProcessChars( const bool bProcessChars )
00063 {
00064 m_bProcessChars = bProcessChars;
00065 }
00066
00067
00068
00069
00070
00071
00072
00073 void CFilterEdit::SetAutoValidate( const bool bAutoValidate, const bool bModal )
00074 {
00075 m_bAutoValidate = bAutoValidate;
00076 m_bModal = bModal;
00077 }
00078
00079
00080
00081
00082
00083
00084 void CFilterEdit::SetShowInvalid (
00085 const bool bShowInvalid, const bool bSetBkOnError, const bool bWavyLineOnError )
00086 {
00087 m_bShowInvalid = bShowInvalid;
00088 m_bSetBkOnError = bSetBkOnError;
00089 m_bWavyLineOnError = bWavyLineOnError;
00090
00091
00092
00093
00094
00095
00096 if ( m_bShowInvalid && !m_bSetBkOnError && !m_bWavyLineOnError )
00097 {
00098 m_bWavyLineOnError = true;
00099 }
00100 }
00101
00102
00103
00104
00105
00106 void CFilterEdit::SetBeepOnInvalid( const bool bBeepOnInvalid )
00107 {
00108 m_bBeepOnInvalid = bBeepOnInvalid;
00109 }
00110
00111
00112
00113
00114
00115 void CFilterEdit::SetBackgroundColourOK( const COLORREF crBkOK )
00116 {
00117 m_crBkOK = crBkOK;
00118 m_brOK.DeleteObject ();
00119 m_brOK.CreateSolidBrush (m_crBkOK);
00120 }
00121
00122
00123
00124
00125
00126 void CFilterEdit::SetForegroundColourOK( const COLORREF crFgOK )
00127 {
00128 m_crFgOK = crFgOK;
00129 }
00130
00131
00132
00133
00134
00135 void CFilterEdit::SetBackgroundColourError( const COLORREF crBkError )
00136 {
00137 m_crBkError = crBkError;
00138 m_brError.DeleteObject ();
00139 m_brError.CreateSolidBrush (m_crBkError);
00140 }
00141
00142
00143
00144
00145
00146 void CFilterEdit::SetForegroundColourError( const COLORREF crFgError )
00147 {
00148 m_crFgError = crFgError;
00149 }
00150
00151
00152
00153
00154
00155 bool CFilterEdit::IsValidChar()
00156 {
00157 return m_bCharValid;
00158 }
00159
00160
00161
00162
00163
00164 const CString &CFilterEdit::GetProposedText() const
00165 {
00166 return m_strProposedText;
00167 }
00168
00169
00170
00171
00172
00173 bool CFilterEdit::IsValidInput()
00174 {
00175 CString str;
00176
00177 GetWindowText (str);
00178
00179 m_bValid = Check( str );
00180
00181 Invalidate ();
00182
00183 if (!m_bValid && m_bBeepOnInvalid)
00184 {
00185 ::MessageBeep( MB_ICONEXCLAMATION );
00186 }
00187
00188 return m_bValid;
00189 }
00190
00191
00192
00193
00194
00195 BEGIN_MESSAGE_MAP( CFilterEdit, CEdit )
00196 ON_WM_CHAR()
00197 ON_WM_KEYDOWN()
00198 ON_WM_KEYUP()
00199 ON_WM_CTLCOLOR_REFLECT()
00200 ON_WM_SETFOCUS()
00201 ON_WM_KILLFOCUS()
00202 ON_WM_PAINT()
00203 END_MESSAGE_MAP()
00204
00205
00206
00207
00208
00209 bool CFilterEdit::ValidateChar( UINT nChar )
00210 {
00211 int iStartIndex = -1;
00212 int iEndIndex = -1;
00213 bool bCharValid = true;
00214
00215 GetSel (iStartIndex, iEndIndex);
00216 GetWindowText (m_strProposedText);
00217
00218 if ( nChar == VK_BACK )
00219 {
00220 if ( iStartIndex == iEndIndex )
00221 {
00222 iStartIndex--;
00223 }
00224
00225
00226 m_strProposedText.Delete( iStartIndex, iEndIndex - iStartIndex );
00227 bCharValid = Match( m_strProposedText );
00228 }
00229 else
00230 {
00231
00232 m_strProposedText.Delete( iStartIndex, iEndIndex - iStartIndex );
00233 m_strProposedText.Insert( iStartIndex, static_cast<TCHAR> (nChar) );
00234 bCharValid = Match( m_strProposedText );
00235 }
00236
00237 return bCharValid;
00238 }
00239
00240 #pragma warning( push )
00241 #pragma warning( disable : 4100 )
00242
00243
00244
00245
00246
00247 bool CFilterEdit::Check( const CString &csText )
00248 {
00249 return true;
00250 }
00251
00252
00253
00254
00255
00256 bool CFilterEdit::Match( const CString &csText )
00257 {
00258 return true;
00259 }
00260
00261 #pragma warning( pop )
00262
00263
00264
00265
00266
00267 void CFilterEdit::ResetValid ()
00268 {
00269 if ( !m_bValid )
00270 {
00271 m_bValid = true;
00272 Invalidate();
00273 }
00274 }
00275
00276
00277
00278
00279
00280 LRESULT CFilterEdit::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
00281 {
00282 bool bExecute = true;
00283 bool bResetValid = false;
00284 LRESULT lResult = 0;
00285
00286 if ( m_bProcessChars )
00287 {
00288 switch ( message )
00289 {
00290 case EM_REPLACESEL:
00291 {
00292 int iStartIndex = -1;
00293 int iEndIndex = -1;
00294 CString strReplace;
00295
00296 GetSel( iStartIndex, iEndIndex );
00297 strReplace = reinterpret_cast<LPCTSTR>( lParam );
00298 GetWindowText( m_strProposedText );
00299 m_strProposedText.Delete( iStartIndex, iEndIndex - iStartIndex );
00300 m_strProposedText.Insert( iStartIndex, strReplace );
00301
00302 bExecute = Match( m_strProposedText );
00303 bResetValid = bExecute;
00304 break;
00305 }
00306
00307
00308
00309
00310
00311 case WM_CLEAR:
00312 bExecute = CanDelete();
00313 bResetValid = bExecute;
00314 break;
00315
00316 case WM_CUT:
00317 bExecute = CanDelete();
00318 bResetValid = bExecute;
00319 break;
00320
00321 case WM_PASTE:
00322 bExecute = CanPaste();
00323 bResetValid = bExecute;
00324 break;
00325
00326 case WM_SETTEXT:
00327 {
00328 const TCHAR *psz = reinterpret_cast<const TCHAR *>( lParam );
00329
00330 bExecute = Match( psz );
00331 bResetValid = bExecute;
00332 break;
00333 }
00334
00335 case WM_UNDO:
00336 bResetValid = true;
00337
00338 default:
00339 break;
00340 }
00341 }
00342
00343 if ( bExecute )
00344 {
00345 lResult = CEdit::WindowProc( message, wParam, lParam );
00346
00347 if ( bResetValid )
00348 {
00349 ResetValid();
00350 }
00351 }
00352
00353 return lResult;
00354 }
00355
00356
00357
00358
00359
00360 bool CFilterEdit::CanDelete()
00361 {
00362 CString csText;
00363 int iStartIndex = -1;
00364 int iEndIndex = -1;
00365
00366 GetWindowText( csText );
00367 GetSel( iStartIndex, iEndIndex );
00368
00369 if ( iStartIndex == iEndIndex )
00370 {
00371 iEndIndex++;
00372 }
00373
00374 csText.Delete( iStartIndex, iEndIndex - iStartIndex );
00375
00376 return Match( csText );
00377 }
00378
00379
00380
00381
00382
00383 bool CFilterEdit::CanPaste()
00384 {
00385 bool bSuccess = OpenClipboard () != 0;
00386
00387 if ( bSuccess )
00388 {
00389 #ifdef _UNICODE
00390 HANDLE hClipMem = ::GetClipboardData( CF_UNICODETEXT );
00391 #else
00392 HANDLE hClipMem = ::GetClipboardData( CF_TEXT );
00393 #endif
00394
00395 bSuccess = hClipMem != 0;
00396
00397 if ( bSuccess )
00398 {
00399 const TCHAR *lpClipMem = (const TCHAR *) ::GlobalLock( hClipMem );
00400
00401 bSuccess = lpClipMem != 0;
00402
00403 if ( bSuccess )
00404 {
00405 CString strClipText;
00406 CString csText;
00407 int iStartIndex = -1;
00408 int iEndIndex = -1;
00409
00410 strClipText.Format( _T("%s"), lpClipMem );
00411 GetWindowText( csText );
00412 GetSel ( iStartIndex, iEndIndex );
00413 csText.Delete( iStartIndex, iEndIndex - iStartIndex );
00414 csText.Insert( iStartIndex, strClipText );
00415
00416 if ( csText.GetLength() > static_cast<int>( GetLimitText() ) )
00417
00418 {
00419 csText = csText.Left( GetLimitText() );
00420
00421 }
00422
00423 bSuccess = Match( csText );
00424 ::GlobalUnlock( hClipMem );
00425 }
00426 }
00427
00428 ::CloseClipboard();
00429 }
00430
00431 return bSuccess;
00432 }
00433
00434
00435
00436
00437
00438 void CFilterEdit::OnChar( UINT nChar, UINT nRepCnt, UINT nFlags )
00439 {
00440 m_bCharValid = !m_bProcessChars || ValidateChar( nChar );
00441
00442 if ( m_bCharValid )
00443 {
00444 CEdit::OnChar( nChar, nRepCnt, nFlags );
00445 }
00446 }
00447
00448
00449
00450
00451
00452 void CFilterEdit::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
00453 {
00454 bool bExecute = true;
00455
00456 ResetValid();
00457
00458 if ( nChar == VK_CONTROL )
00459 {
00460 m_bControlDown = true;
00461 }
00462 else if ( nChar == VK_DELETE )
00463 {
00464 if ( m_bProcessChars )
00465 {
00466 bExecute = CanDelete();
00467 }
00468 }
00469 else if ( ( nChar == 'x' || nChar == 'X' ) && m_bControlDown )
00470 {
00471 if ( m_bProcessChars )
00472 {
00473 bExecute = CanDelete();
00474
00475 if ( bExecute )
00476 {
00477
00478 bExecute = false;
00479 SendMessage( WM_CUT, 0, 0 );
00480 }
00481 }
00482 }
00483
00484 else if ( ( nChar == 'v' || nChar == 'V' ) && m_bControlDown )
00485 {
00486 SendMessage( WM_PASTE, 0, 0 );
00487 }
00488
00489 if ( bExecute )
00490 {
00491 CEdit::OnKeyDown( nChar, nRepCnt, nFlags );
00492 }
00493 }
00494
00495
00496
00497
00498
00499 void CFilterEdit::OnKeyUp( UINT nChar, UINT nRepCnt, UINT nFlags )
00500 {
00501 if ( nChar == VK_CONTROL )
00502 {
00503 m_bControlDown = false;
00504 }
00505
00506 CEdit::OnKeyUp( nChar, nRepCnt, nFlags );
00507 }
00508
00509
00510
00511
00512
00513 HBRUSH CFilterEdit::CtlColor( CDC *pDC, UINT )
00514 {
00515
00516
00517
00518
00519 HBRUSH hbr = m_brOK;
00520
00521
00522
00523
00524
00525 if ( m_bValid || !m_bSetBkOnError )
00526 {
00527 pDC->SetBkColor ( m_crBkOK );
00528 pDC->SetTextColor( m_crFgOK );
00529 }
00530 else if ( m_bShowInvalid && m_bSetBkOnError )
00531 {
00532
00533
00534
00535
00536 hbr = m_brError;
00537 pDC->SetBkColor ( m_crBkError );
00538 pDC->SetTextColor( m_crFgError );
00539 }
00540
00541 return hbr;
00542 }
00543
00544
00545
00546
00547
00548 void CFilterEdit::OnSetFocus( CWnd *pOldWnd )
00549 {
00550 CEdit::OnSetFocus( pOldWnd );
00551 }
00552
00553
00554
00555
00556
00557 void CFilterEdit::OnKillFocus( CWnd *pNewWnd )
00558 {
00559 bool bValid = true;
00560
00561 if ( m_bAutoValidate )
00562 {
00563
00564
00565
00566
00567 if ( pNewWnd && pNewWnd != GetParent() && pNewWnd->GetDlgCtrlID() != IDCANCEL )
00568 {
00569 bValid = IsValidInput();
00570 }
00571 else
00572 {
00573 bValid = true;
00574 }
00575 }
00576
00577 if ( bValid || !m_bModal )
00578 {
00579 CEdit::OnKillFocus( pNewWnd );
00580 }
00581 else
00582 {
00583 SetFocus();
00584 }
00585 }
00586
00587
00588
00589
00590
00591 void CFilterEdit::OnPaint()
00592 {
00593 CClientDC dc (this);
00594
00595
00596 Default();
00597
00598 if ( !m_bValid && m_bShowInvalid && m_bWavyLineOnError )
00599 {
00600 CFont *pFont = GetFont();
00601 CPen *pPen = dc.GetCurrentPen();
00602
00603 LOGPEN lp;
00604 CPen MyPen;
00605 CRect rect;
00606 CString csText;
00607 CSize size;
00608 int iX = 0;
00609 const int iIncrement = 2;
00610
00611
00612
00613 dc.SelectObject( pFont );
00614
00615
00616
00617 pPen->GetLogPen( &lp );
00618 lp.lopnColor = m_bSetBkOnError ? m_crFgError : m_crBkError;
00619 MyPen.CreatePenIndirect( &lp );
00620 dc.SelectObject( &MyPen );
00621
00622
00623
00624 GetRect ( &rect );
00625 GetWindowText( csText );
00626
00627
00628
00629 size = dc.GetTextExtent( csText.Mid( CharFromPos( CPoint( rect.left + 1, rect.top ) ) ) );
00630
00631
00632 if ( size.cx == 0 )
00633 size.cx = iIncrement * 3;
00634
00635 else if ( size.cx > rect.right )
00636 size.cx = rect.right;
00637
00638
00639
00640 iX = rect.left;
00641
00642
00643
00644 dc.MoveTo( rect.left, rect.bottom );
00645
00646
00647
00648 while ( iX < size.cx + rect.left )
00649 {
00650 iX += iIncrement;
00651
00652 if ( iX > size.cx + rect.left )
00653 break;
00654
00655 dc.LineTo( iX, rect.bottom + iIncrement );
00656 iX += iIncrement;
00657
00658 if ( iX > size.cx + rect.left )
00659 break;
00660
00661 dc.LineTo( iX, rect.bottom );
00662 }
00663 }
00664
00665
00666 }
00667
00668
00669
00670