www.pudn.com > vistaListCtrlDemo.zip > ListEdit.h


 
#pragma once 
 
#include "ListTypes.h" 
 
class CListEdit : public CWindowImpl< CListEdit, CEdit > 
{ 
public: 
	CListEdit() 
	{ 
		m_nItem = NULL_ITEM; 
		m_nSubItem = NULL_SUBITEM; 
		m_nFlags = ITEM_FLAGS_NONE; 
		m_nExitChar = 0; 
	} 
	 
	~CListEdit() 
	{ 
	} 
 
protected: 
	int m_nItem; 
	int m_nSubItem; 
	UINT m_nFlags; 
	TCHAR m_nExitChar; 
	CFont m_fntEditFont; 
	 
public: 
	BOOL Create( HWND hWndParent, int nItem, int nSubItem, CRect& rcRect, UINT nFlags, LPCTSTR lpszItemText ) 
	{ 
		m_nItem = nItem; 
		m_nSubItem = nSubItem; 
		m_nFlags = nFlags; 
		m_nExitChar = 0; 
		 
		// destroy old edit control... 
		if ( IsWindow() ) 
			DestroyWindow(); 
		 
		DWORD dwStyle = WS_CHILD | ES_AUTOHSCROLL; 
		 
		// right-justify numbers 
		if ( nFlags & ( ITEM_FLAGS_EDIT_NUMBER | ITEM_FLAGS_EDIT_FLOAT ) ) 
			dwStyle |= ES_RIGHT; 
		 
		if ( nFlags & ITEM_FLAGS_EDIT_UPPER ) 
			dwStyle |= ES_UPPERCASE; 
		 
		// create edit control 
		if ( CWindowImpl< CListEdit, CEdit >::Create( hWndParent, CRect( rcRect.left + 2, rcRect.top + 3, rcRect.right - 3, rcRect.bottom - 2 ), NULL, dwStyle ) == NULL ) 
			return FALSE; 
		 
		// get system message font 
		CLogFont logFont; 
		logFont.SetMessageBoxFont(); 
		if ( !m_fntEditFont.IsNull() ) 
			m_fntEditFont.DeleteObject(); 
		if ( m_fntEditFont.CreateFontIndirect( &logFont ) == NULL ) 
			return FALSE; 
 
		SetFont( m_fntEditFont ); 
		SetMargins( ITEM_EDIT_MARGIN, ITEM_EDIT_MARGIN );		 
		SetWindowText( lpszItemText ); 
		 
		// show edit control 
		ShowWindow( SW_SHOW ); 
		 
		SetSelAll(); 
		SetFocus(); 
		 
		return TRUE; 
	} 
	 
	BOOL IsValid( TCHAR nChar ) 
	{ 
		// validate number and float input 
		if ( !( m_nFlags & ( ITEM_FLAGS_EDIT_NUMBER | ITEM_FLAGS_EDIT_FLOAT ) ) || nChar == VK_BACK ) 
			return TRUE; 
		 
		CString strValue; 
		int nValueLength = GetWindowTextLength() + 1; 
		GetWindowText( strValue.GetBuffer( nValueLength ), nValueLength ); 
		strValue.ReleaseBuffer(); 
		 
		// get selected positions 
		int nStartChar; 
		int nEndChar; 
		GetSel( nStartChar, nEndChar ); 
		 
		// are we changing the sign? 
		if ( ( m_nFlags & ITEM_FLAGS_EDIT_NEGATIVE ) && nChar == _T( '-' ) ) 
		{ 
			BOOL bNegative = FALSE; 
			if ( m_nFlags & ITEM_FLAGS_EDIT_FLOAT ) 
			{ 
				double dblValue = _tstof( strValue ); 
				bNegative = ( dblValue < 0 ); 
				strValue.Format( _T( "%lf" ), -dblValue ); 
			} 
			else 
			{ 
				long lValue = _ttol( strValue ); 
				bNegative = ( lValue < 0 ); 
				strValue.Format( _T( "%ld" ), -lValue ); 
			} 
			 
			SetWindowText( strValue ); 
			 
			// restore select position 
			SetSel( bNegative ? nStartChar - 1 : nStartChar + 1, bNegative ? nEndChar - 1 : nEndChar + 1 ); 
			return FALSE; 
		} 
		 
		// construct new value string using entered character 
		CString strNewValue = strValue.Left( nStartChar ) + nChar + strValue.Right( strValue.GetLength() - nEndChar ); 
		 
		int nGreaterThan = 0; 
		int nLessThan = 0; 
		int nEquals = 0; 
		int nDecimalPoint = 0; 
		 
		int nNegativeIndex = -1; 
		int nGreaterIndex = -1; 
		int nLessIndex = -1; 
		int nEqualIndex = -1; 
		int nDecimalIndex = -1; 
		int nDigitIndex = -1; 
		 
		for ( int nCharIndex = 0; nCharIndex < strNewValue.GetLength(); nCharIndex++ ) 
		{ 
			TCHAR nCharValue = strNewValue[ nCharIndex ]; 
			switch ( nCharValue ) 
			{ 
				case _T( '-' ):	nNegativeIndex = nCharIndex; 
								break; 
				case _T( '>' ):	if ( !( m_nFlags & ITEM_FLAGS_EDIT_OPERATOR ) ) 
									return FALSE; 
								nGreaterIndex = nCharIndex; 
								nGreaterThan++; 
								break; 
				case _T( '<' ):	if ( !( m_nFlags & ITEM_FLAGS_EDIT_OPERATOR ) ) 
									return FALSE; 
								nLessIndex = nCharIndex; 
								nLessThan++; 
								break; 
				case _T( '=' ):	if ( !( m_nFlags & ITEM_FLAGS_EDIT_OPERATOR ) ) 
									return FALSE; 
								nEqualIndex = nCharIndex; 
								nEquals++; 
								break; 
				case _T( '.' ):	if ( !( m_nFlags & ITEM_FLAGS_EDIT_FLOAT ) ) 
									return FALSE; 
								nDecimalIndex = nCharIndex; 
								nDecimalPoint++; 
								break; 
				default:		if ( !_istdigit( nCharValue ) ) 
									return FALSE; 
								if ( nDigitIndex < 0 ) 
									nDigitIndex = nCharIndex; 
								break; 
			} 
 
			// invalid if text contains more than one '>', '<', '=' or '.' 
			if ( nGreaterThan > 1 || nLessThan > 1 || nEquals > 1 || nDecimalPoint > 1 ) 
				return FALSE; 
		} 
 
		// invalid if text contains '=>' or '=<' 
		if ( nGreaterIndex != -1 && nEqualIndex != -1 && nGreaterIndex > nEqualIndex ) 
			return FALSE; 
		if ( nLessIndex != -1 && nEqualIndex != -1 && nLessIndex > nEqualIndex ) 
			return FALSE; 
 
		// invalid if digits exist before operator 
		if ( nDigitIndex != -1 && nGreaterIndex != -1 && nGreaterIndex > nDigitIndex ) 
			return FALSE; 
		if ( nDigitIndex != -1 && nLessIndex != -1 && nLessIndex > nDigitIndex ) 
			return FALSE; 
		if ( nDigitIndex != -1 && nEqualIndex != -1 && nEqualIndex > nDigitIndex ) 
			return FALSE; 
		if ( nDigitIndex != -1 && nNegativeIndex != -1 && nNegativeIndex > nDigitIndex ) 
			return FALSE; 
		 
		return TRUE; 
	} 
	 
	BEGIN_MSG_MAP_EX(CListEdit) 
		MSG_WM_KILLFOCUS(OnKillFocus) 
		MSG_WM_GETDLGCODE(OnGetDlgCode) 
		MSG_WM_CHAR(OnChar) 
	END_MSG_MAP_EX() 
	 
	void OnKillFocus( HWND hNewWnd ) 
	{ 
		CWindow wndParent( GetParent() ); 
		if ( wndParent.IsWindow() ) 
		{ 
			CString strValue; 
			int nValueLength = GetWindowTextLength() + 1; 
			GetWindowText( strValue.GetBuffer( nValueLength ), nValueLength ); 
			strValue.ReleaseBuffer(); 
			 
			CListNotify listNotify; 
			listNotify.m_hdrNotify.hwndFrom = m_hWnd; 
			listNotify.m_hdrNotify.idFrom = GetDlgCtrlID(); 
			listNotify.m_hdrNotify.code = LCN_ENDEDIT; 
			listNotify.m_nItem = m_nItem; 
			listNotify.m_nSubItem = m_nSubItem; 
			listNotify.m_nExitChar = m_nExitChar; 
			listNotify.m_lpszItemText = strValue; 
			listNotify.m_lpItemDate = NULL; 
 
			// forward notification to parent 
			FORWARD_WM_NOTIFY( wndParent, listNotify.m_hdrNotify.idFrom, &listNotify.m_hdrNotify, ::SendMessage ); 
		} 
		 
		ShowWindow( SW_HIDE ); 
	} 
	 
	UINT OnGetDlgCode( LPMSG lpMessage ) 
	{ 
		return DLGC_WANTALLKEYS; 
	} 
	 
	void OnChar( TCHAR nChar, UINT nRepCnt, UINT nFlags ) 
	{ 
		switch ( nChar ) 
		{ 
			case VK_TAB: 
			case VK_RETURN: 
			case VK_ESCAPE:	{ 
								m_nExitChar = nChar; 
								CWindow wndParent( GetParent() ); 
								if ( wndParent.IsWindow() ) 
									wndParent.SetFocus(); 
							} 
							break; 
			default:		SetMsgHandled( !IsValid( nChar ) ); 
							break; 
		} 
	} 
};