/******************************************** ** 工作室:S&P工作室 ** 作者 :张东斌 ** 日期 :2007年6月 *********************************************/ #include "StdAfx.h" #include "SPVC80Helpers.h" #include "SPDrawHelpers.h" #include "SPPropertyGridInplaceEdit.h" #include "SPPropertyGridInplaceButton.h" #include "SPPropertyGridInplaceList.h" #include "SPPropertyGridItem.h" #include "SPPropertyGrid.h" #include "SPPropertyGridDefines.h" #define SAFE_CALLPTR(p, f) if (p) p->f #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CSPPropertyGridItem IMPLEMENT_DYNAMIC( CSPPropertyGridItem , CCmdTarget ) CSPPropertyGridItem::CSPPropertyGridItem( CString strCaption , LPCTSTR strValue , CString * pBindString ) { Init(); SetPrompt( strCaption ); m_strValue = strValue; BindToString( pBindString ); } CSPPropertyGridItem::CSPPropertyGridItem( UINT nID , LPCTSTR strValue , CString * pBindString ) { Init(); m_nID = nID; CString strPrompt; if ( strPrompt.LoadString( nID ) ) { SetPrompt( strPrompt ); } m_strValue = strValue; BindToString( pBindString ); } CSPPropertyGridItem::~CSPPropertyGridItem() { if ( m_pGrid && m_pGrid->m_pSelected == this ) { m_pGrid->m_pSelected = NULL; } m_pChilds->Clear(); if ( GetInplaceButton().m_pItem == this ) { GetInplaceButton().DestroyItem(); } if ( GetInplaceList().m_pItem == this ) { GetInplaceList().DestroyItem(); } if ( GetInplaceEdit().m_pItem == this ) { GetInplaceEdit().DestroyItem(); } m_pChilds->InternalRelease(); m_pConstraints->m_pItem = NULL; m_pConstraints->InternalRelease(); } void CSPPropertyGridItem::SetPrompt( CString strText ) { int nIndex = strText.Find( '\n' ); if ( nIndex == -1 ) { m_strCaption = strText; } else { m_strCaption = strText.Left( nIndex ); m_strDescription = strText.Mid( nIndex + 1 ); } } void CSPPropertyGridItem::Init() { m_bExpanded = FALSE; m_nIndex = -1; m_bVisible = FALSE; m_pParent = 0; m_pGrid = 0; m_nIndent = 0; m_strValue = ""; m_bReadOnly = FALSE; m_bCategory = FALSE; m_nID = 0; m_nFlags = SPGridItemHasEdit; m_pConstraints = new CSPPropertyGridItemConstraints( this ); m_pConstraints->SetCurrent( -1 ); m_pBindString = 0; m_bConstraintEdit = FALSE; m_bUseMask = FALSE; m_bPassword = FALSE; m_chPrompt = _T( '*' ); m_dwData = 0; EnableAutomation(); m_pChilds = new CSPPropertyGridItems(); } CSPPropertyGridItem * CSPPropertyGridItem::AddChildItem( CSPPropertyGridItem * pItem ) { return InsertChildItem( m_pChilds->GetCount(),pItem ); } CSPPropertyGridItem * CSPPropertyGridItem::InsertChildItem( int nIndex , CSPPropertyGridItem * pItem ) { ASSERT( !pItem->IsCategory() || IsCategory() ); if ( nIndex < 0 || nIndex > m_pChilds->GetCount() ) { nIndex = m_pChilds->GetCount(); } m_pChilds->InsertAt( nIndex,pItem ); pItem->m_pGrid = pItem->m_pChilds->m_pGrid = m_pGrid; ASSERT( pItem->m_pParent == NULL ); pItem->m_pParent = this; pItem->m_nIndent = m_nIndent + 1; pItem->OnAddChildItem(); if ( m_bVisible ) { if ( m_bExpanded ) { m_pGrid->SetPropertySort( m_pGrid->m_properetySort,TRUE ); } else if ( m_pGrid->GetSafeHwnd() && m_pChilds->GetCount() == 1 ) { m_pGrid->Invalidate( FALSE ); } } return pItem; } void CSPPropertyGridItem::Collapse() { if ( !m_bExpanded ) { return; } if ( m_pGrid->m_nLockUpdate == 0 ) { if ( m_pGrid->GetSafeHwnd() && m_bVisible ) { m_pGrid->_DoCollapse( this ); m_pGrid->OnSelectionChanged(); } } m_bExpanded = FALSE; if ( m_pGrid->GetSafeHwnd() ) { m_pGrid->GetParent()->GetOwner()->SendMessage( SPWM_PROPERTYGRID_NOTIFY,SP_PGN_ITEMEXPANDCHANGED,( LPARAM )this ); } } void CSPPropertyGridItem::Expand() { if ( m_bExpanded ) { return; } if ( m_pGrid->m_nLockUpdate == 0 ) { if ( m_pGrid->GetSafeHwnd() && m_bVisible ) { m_pGrid->_DoExpand( this,m_nIndex ); m_pGrid->_RefreshIndexes(); m_pGrid->OnSelectionChanged(); } } m_bExpanded = TRUE; if ( m_pGrid->GetSafeHwnd() ) { m_pGrid->GetParent()->GetOwner()->SendMessage( SPWM_PROPERTYGRID_NOTIFY,SP_PGN_ITEMEXPANDCHANGED,( LPARAM )this ); } } BOOL CSPPropertyGridItem::HasParent( CSPPropertyGridItem * pParent ) { if ( m_pParent == NULL ) { return FALSE; } if ( m_pParent == pParent ) { return TRUE; } return m_pParent->HasParent( pParent ); } void CSPPropertyGridItem::Select() { ASSERT( m_pGrid ); if ( m_bVisible ) { m_pGrid->SetCurSel( m_nIndex ); m_pGrid->OnSelectionChanged(); } } void CSPPropertyGridItem::OnDeselect() { GetInplaceButton().HideWindow(); OnValidateEdit(); } void CSPPropertyGridItem::OnValidateEdit() { GetInplaceEdit().HideWindow(); if ( GetInplaceEdit().GetSafeHwnd() && GetInplaceEdit().m_pItem == this ) { CString strValue; GetInplaceEdit().GetWindowText( strValue ); if ( m_strValue != strValue ) { OnValueChanged( strValue ); } } } void CSPPropertyGridItem::SetEditText( CString str ) { if ( !m_pGrid ) { return; } if ( GetInplaceEdit().GetSafeHwnd() && GetInplaceEdit().m_pItem == this ) { GetInplaceEdit().SetWindowText( str ); } } void CSPPropertyGridItem::SetValue( CString strValue ) { m_strValue = strValue; if ( m_pBindString ) { *m_pBindString = strValue; } SetEditText( m_strValue ); if ( m_pGrid && m_pGrid->m_hWnd ) { m_pGrid->Invalidate( FALSE ); } } void CSPPropertyGridItem::OnValueChanged( CString strValue ) { SetValue( strValue ); m_pGrid->Invalidate( FALSE ); m_pGrid->GetParent()->GetOwner()->SendMessage( SPWM_PROPERTYGRID_NOTIFY,SP_PGN_ITEMVALUE_CHANGED,( LPARAM )this ); } void CSPPropertyGridItem::OnSelect() { ASSERT( m_bVisible ); if ( !m_bReadOnly && ( m_nFlags & ( SPGridItemHasComboButton | SPGridItemHasExpandButton ) ) ) { GetInplaceButton().Create( this,GetItemRect() ); } else { GetInplaceButton().HideWindow(); } if ( m_nFlags & SPGridItemHasEdit ) { GetInplaceEdit().SetValue( m_strValue ); GetInplaceEdit().Create( this,GetValueRect() ); GetInplaceEdit().SetReadOnly( m_bReadOnly ); } else { GetInplaceEdit().HideWindow(); } } void CSPPropertyGridItem::OnInplaceButtonDown() { if ( GetReadOnly() ) { return; } if ( m_pGrid->GetParent()->GetOwner()->SendMessage( SPWM_PROPERTYGRID_NOTIFY,SP_PGN_INPLACEBUTTONDOWN,( LPARAM )this ) == TRUE ) { return; } if ( ( m_nFlags & SPGridItemHasComboButton ) && !m_pConstraints->IsEmpty() ) { GetInplaceList().Create( this,GetItemRect() ); m_pGrid->Invalidate( FALSE ); } } CRect CSPPropertyGridItem::GetValueRect() { ASSERT( m_bVisible ); CRect rc = GetItemRect(); CRect rcValue ( m_pGrid->GetDividerPos() + 1,rc.top + 1,rc.right,rc.bottom - 1 ); if ( m_nFlags & ( SPGridItemHasComboButton | SPGridItemHasExpandButton ) ) { if ( GetInplaceButton().m_pItem == this && GetInplaceButton().GetStyle() & WS_VISIBLE ) { rcValue.right -= GetSystemMetrics( SM_CXHTHUMB ); } } return rcValue; } CRect CSPPropertyGridItem::GetItemRect() { CRect rc; m_pGrid->GetItemRect( m_nIndex,rc ); return rc; } BOOL CSPPropertyGridItem::OnChar( UINT nChar ) { ASSERT( nChar != VK_TAB ); if ( m_nFlags & SPGridItemHasEdit ) { OnSelect(); GetInplaceEdit().SetFocus(); GetInplaceEdit().SetSel( 0,-1 ); if ( nChar != VK_TAB ) GetInplaceEdit().SendMessage( WM_CHAR,nChar ); return TRUE; } else if ( nChar == VK_TAB ) { CSPPropertyGridInplaceButton& wndButton = GetInplaceButton(); if ( wndButton.GetSafeHwnd() && wndButton.IsWindowVisible() && wndButton.GetItem() == this ) { wndButton.SetFocus(); } } return FALSE; } void CSPPropertyGridItem::OnLButtonDblClk() { if ( HasChilds() ) { if ( m_bExpanded ) { Collapse(); } else { Expand(); } } else { OnSelect(); if ( m_nFlags & SPGridItemHasEdit ) { if ( !GetReadOnly() && GetInplaceEdit().SelectConstraint( +1,TRUE ) ) { OnValidateEdit(); } else { GetInplaceEdit().SetFocus(); GetInplaceEdit().SetSel( 0,-1 ); } } else if ( !GetReadOnly() ) { CSPPropertyGridItemConstraints *pList = GetConstraints(); if ( pList->IsEmpty() ) return ; int nIndex = pList->FindConstraint( m_strValue ); nIndex += +1; if ( nIndex >= pList->GetCount() ) nIndex = 0; if ( nIndex < 0 ) nIndex = ( ULONG ) pList->GetCount() - 1; pList->SetCurrent( nIndex ); OnValueChanged( pList->GetAt( nIndex ) ); } } } BOOL CSPPropertyGridItem::OnLButtonDown( UINT , CPoint point ) { Select(); int nOffset = ( m_nIndent - ( IsCategory() ? 0 : 1 ) ) * SP_PGI_EXPAND_BORDER; if ( point.x >= nOffset && point.x <= SP_PGI_EXPAND_BORDER + nOffset ) { if ( m_bExpanded ) { Collapse(); } else { Expand(); } } CRect rc = GetValueRect(); if ( ( m_nFlags & SPGridItemHasEdit ) && rc.PtInRect( point ) ) { mouse_event( GetSystemMetrics( SM_SWAPBUTTON ) ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN,0,0,0,0 ); } return TRUE; } void CSPPropertyGridItem::BindToString( CString * pBindString ) { m_pBindString = pBindString; if ( m_pBindString ) { *m_pBindString = m_strValue; } } void CSPPropertyGridItem::OnBeforeInsert() { if ( m_pBindString && *m_pBindString != m_strValue ) { m_strValue = *m_pBindString; } } CSPPropertyGridInplaceEdit & CSPPropertyGridItem::GetInplaceEdit() { if ( m_pGrid ) { return m_pGrid->m_wndEdit; } static CSPPropertyGridInplaceEdit wndEdit; return wndEdit; } CSPPropertyGridInplaceButton & CSPPropertyGridItem::GetInplaceButton() { if ( m_pGrid ) { return m_pGrid->m_wndButton; } static CSPPropertyGridInplaceButton wndButton; return wndButton; } CSPPropertyGridInplaceList & CSPPropertyGridItem::GetInplaceList() { if ( m_pGrid ) { return m_pGrid->m_wndListBox; } static CSPPropertyGridInplaceList wndListBox; return wndListBox; } // Deletes the item. void CSPPropertyGridItem::Remove() { CSPPropertyGridItems * pItems = GetParentItem() == 0 ? m_pGrid->m_pCategories : GetParentItem()->m_pChilds; ASSERT( pItems ); pItems->m_arrItems.RemoveAt( pItems->Find( this ) ); m_pGrid->Refresh(); InternalRelease(); } BOOL CSPPropertyGridItem::IsSelected() { return m_pGrid && m_pGrid->GetSelectedItem() == this; } void CSPPropertyGridItem::Refresh( BOOL bInvalidate /*= TRUE*/ ) { if ( m_pGrid && m_pGrid->GetSafeHwnd() ) { if ( IsSelected() ) { OnDeselect(); OnSelect(); } if ( bInvalidate ) { m_pGrid->Invalidate( FALSE ); } } } void CSPPropertyGridItem::SetReadOnly( BOOL bReadOnly ) { if ( m_bReadOnly != bReadOnly ) { m_bReadOnly = bReadOnly; Refresh( TRUE ); } } void CSPPropertyGridItem::SetMask( LPCTSTR strMask , LPCTSTR strLiteral , TCHAR chPrompt /*= _T('_')*/ ) { m_bUseMask = TRUE; m_strMask = strMask; m_strLiteral = strLiteral; m_chPrompt = chPrompt; Refresh( FALSE ); } CString CSPPropertyGridItem::GetViewValue() { CString str = GetValue(); if ( m_bPassword ) { return CString( m_chPrompt,str.GetLength() ); } return str; } CString CSPPropertyGridItem::GetMaskedText() { if ( m_bUseMask ) { int nLength = m_strValue.GetLength(); CString strBuffer; for ( int i = 0; i < nLength; ++i ) { if ( m_strLiteral[i] == m_chPrompt ) { strBuffer += m_strValue.GetAt( i ); } } return strBuffer; } else { return m_strValue; } } void CSPPropertyGridItem::SetMaskedText( LPCTSTR lpszMaskedText ) { CString strMaskedText = lpszMaskedText; if ( m_bUseMask ) { int nLen = strMaskedText.GetLength(); int x = 0; m_strValue = m_strLiteral; for ( int i = 0; ( i < m_strValue.GetLength() ) && ( x < nLen ); i++ ) { if ( strMaskedText[x] == m_strValue[i] ) { x ++; } else if ( m_strValue[i] == m_chPrompt ) { m_strValue.SetAt( i,strMaskedText[x] ); x ++; } } } else { m_strValue = strMaskedText; } SetValue( m_strValue ); } void CSPPropertyGridItem::SetDescription( LPCTSTR lpszDescription ) { m_strDescription = lpszDescription; if ( IsSelected() ) { GetGrid()->GetParent()->Invalidate( FALSE ); } } ///////////////////////////////////////////////////////////////////////////// // CSPPropertyGridItems CSPPropertyGridItems::CSPPropertyGridItems() { m_pGrid = 0; } void CSPPropertyGridItems::Clear() { if ( m_pGrid ) { if ( m_pGrid->m_nLockUpdate == 0 ) m_pGrid->ResetContent(); m_pGrid->m_nLockUpdate++; } for ( int i = 0; i < GetCount(); i++ ) { m_arrItems[i]->InternalRelease(); } m_arrItems.RemoveAll(); if ( m_pGrid ) { m_pGrid->m_nLockUpdate--; if ( m_pGrid->m_nLockUpdate == 0 ) m_pGrid->Refresh(); } } CSPPropertyGridItem * CSPPropertyGridItems::GetAt( int nIndex ) { if ( nIndex >= 0 && nIndex < GetCount() ) { return m_arrItems.GetAt( nIndex ); } return 0; } void CSPPropertyGridItems::RemoveAt( int nIndex ) { ASSERT( m_pGrid ); CSPPropertyGridItem * pItem = GetAt( nIndex ); if ( pItem ) { m_arrItems.RemoveAt( nIndex ); m_pGrid->Refresh(); pItem->InternalRelease(); } } int CSPPropertyGridItems::Find( CSPPropertyGridItem * pItem ) { for ( int i = 0; i < GetCount(); i++ ) { if ( m_arrItems[i] == pItem ) { return i; } } return -1; } void CSPPropertyGridItems::AddTail( CSPPropertyGridItems * pItems ) { ASSERT( this != pItems ); for ( int i = 0; i < pItems->GetCount(); i++ ) { AddTail( pItems->GetAt( i ) ); } } int CSPPropertyGridItems::CompareFunc( const CSPPropertyGridItem ** ppItem1 , const CSPPropertyGridItem ** ppItem2 ) { return ( *ppItem1 )->GetCaption().Compare( ( *ppItem2 )->GetCaption() ); } void CSPPropertyGridItems::Sort() { typedef int ( _cdecl *GENERICCOMPAREFUNC )( const void * , const void * ); qsort( m_arrItems.GetData(),m_arrItems.GetSize(),sizeof( CSPPropertyGridItem * ),( GENERICCOMPAREFUNC ) CompareFunc ); } CSPPropertyGridItem * CSPPropertyGridItems::FindItem( CString strCaption ) { for ( int i = 0; i < GetCount(); i++ ) { CSPPropertyGridItem * pItem = GetAt( i ); if ( pItem->GetCaption() == strCaption ) return pItem; CSPPropertyGridItem * pChild = pItem->m_pChilds->FindItem( strCaption ); if ( pChild ) return pChild; } return NULL; } CSPPropertyGridItem * CSPPropertyGridItems::FindItem( UINT nID ) { for ( int i = 0; i < GetCount(); i++ ) { CSPPropertyGridItem * pItem = GetAt( i ); if ( pItem->GetID() == nID ) return pItem; CSPPropertyGridItem * pChild = pItem->m_pChilds->FindItem( nID ); if ( pChild ) return pChild; } return NULL; } ////////////////////////////////////////////////////////////////////////// // CSPPropertyGridItemConstraint CSPPropertyGridItemConstraint::CSPPropertyGridItemConstraint() { m_nIndex = 0; m_dwData = 0; } ///////////////////////////////////////////////////////////////////////////// // CSPPropertyGridItemConstraints // Summary: Constructs a CSPPropertyGridItemConstraints object CSPPropertyGridItemConstraints::CSPPropertyGridItemConstraints( CSPPropertyGridItem * pItem ) { m_pItem = pItem; } CSPPropertyGridItemConstraints::~CSPPropertyGridItemConstraints() { RemoveAll(); } CSPPropertyGridItemConstraint * CSPPropertyGridItemConstraints::AddConstraint( CString str , DWORD dwData ) { CSPPropertyGridItemConstraint * pConstaint = new CSPPropertyGridItemConstraint(); pConstaint->m_strConstraint = str; pConstaint->m_dwData = dwData; pConstaint->m_nIndex = ( int ) m_arrConstraints.Add( pConstaint ); SAFE_CALLPTR( m_pItem,OnConstraintsChanged() ); return pConstaint; } CString CSPPropertyGridItemConstraints::GetAt( int nIndex ) { return nIndex >= 0 && nIndex < GetCount() ? m_arrConstraints.GetAt( nIndex )->m_strConstraint : _T( "" ); } void CSPPropertyGridItemConstraints::RemoveAll() { for ( int i = 0; i < GetCount(); i++ ) { m_arrConstraints[i]->InternalRelease(); } m_arrConstraints.RemoveAll(); SAFE_CALLPTR( m_pItem,OnConstraintsChanged() ); } void CSPPropertyGridItemConstraints::RemoveAt( int nIndex ) { m_arrConstraints[nIndex]->InternalRelease(); m_arrConstraints.RemoveAt( nIndex ); for ( int i = nIndex; i < GetCount(); i++ ) { m_arrConstraints[i]->m_nIndex = i; } SAFE_CALLPTR( m_pItem,OnConstraintsChanged() ); } int CSPPropertyGridItemConstraints::FindConstraint( CString str ) { for ( int i = 0; i < GetCount(); i++ ) { if ( str == GetAt( i ) ) { return i; } } return -1; } int CSPPropertyGridItemConstraints::FindConstraint( DWORD dwData ) { for ( int i = 0; i < GetCount(); i++ ) { if ( dwData == GetConstraintAt( i )->m_dwData ) { return i; } } return -1; } CSPPropertyGridItemConstraint * CSPPropertyGridItemConstraints::GetConstraintAt( int nIndex ) { return m_arrConstraints[nIndex]; } int CSPPropertyGridItemConstraints::CompareFunc( const CSPPropertyGridItemConstraint ** ppConstraint1 , const CSPPropertyGridItemConstraint ** ppConstraint2 ) { return ( *ppConstraint1 )->m_strConstraint.Compare( ( *ppConstraint2 )->m_strConstraint ); } void CSPPropertyGridItemConstraints::Sort() { typedef int ( _cdecl *GENERICCOMPAREFUNC )( const void * , const void * ); qsort( m_arrConstraints.GetData(),( size_t ) m_arrConstraints.GetSize(),sizeof( CSPPropertyGridItemConstraint * ),( GENERICCOMPAREFUNC ) CompareFunc ); } ////////////////////////////////////////////////////////////////////////// // CSPPropertyGridItemCategory CSPPropertyGridItemCategory::CSPPropertyGridItemCategory( CString strCaption ) : CSPPropertyGridItem( strCaption ) { m_bCategory = TRUE; m_nFlags = 0; } CSPPropertyGridItemCategory::CSPPropertyGridItemCategory( UINT nID ) : CSPPropertyGridItem( nID ) { m_bCategory = TRUE; m_nFlags = 0; } /////////////////////////////////////////////////////////////////////////////////// // Acteve X Methods //