2026-10-04 00:04:20 +08:00
#include "stdafx.h"
2026-09-28 15:28:50 +08:00
#include "SuperGridCtrlEx.h"
#include "ComboInListView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE [] = __FILE__ ;
#endif
CSuperGridCtrlEx :: CSuperGridCtrlEx ()
{
m_bDrag = TRUE ;
}
CSuperGridCtrlEx ::~ CSuperGridCtrlEx ()
{
}
BEGIN_MESSAGE_MAP ( CSuperGridCtrlEx , CSuperGridCtrl )
//{{AFX_MSG_MAP(CSuperGridCtrlEx)
ON_WM_CREATE ()
//}}AFX_MSG_MAP
END_MESSAGE_MAP ()
int CSuperGridCtrlEx :: OnCreate ( LPCREATESTRUCT lpCreateStruct )
{
if ( CSuperGridCtrl :: OnCreate ( lpCreateStruct ) == - 1 )
return - 1 ;
return 0 ;
}
//helper function to copy CItemInfo used when drag/drop you must override this this function to suit your own CItemInfo class
CItemInfo * CSuperGridCtrlEx :: CopyData ( CItemInfo * lpSrc )
{
ASSERT ( lpSrc != NULL );
CItemInfo * lpDest = new CItemInfo ;
//well okay I put all the copy thing in one function, located in CItemInfo class,
//so you should check out this function, remember to modify this function each time you add new data to CItemInfo class.
lpDest -> CopyObjects ( lpSrc );
return lpDest ;
}
//override, like red!
COLORREF CSuperGridCtrlEx :: GetCellRGB ()
{
return RGB ( 192 , 192 , 192 );
}
//this is my override of GetIcon, override this to set what ever icon suits you
int CSuperGridCtrlEx :: GetIcon ( const CTreeItem * pItem )
{
if ( pItem != NULL )
{
int n = GetData ( pItem ) -> GetImage ();
if ( n !=- 1 )
return n ;
int iImage = 0 ;
if ( ItemHasChildren ( pItem ))
{
IsCollapsed ( pItem ) ? iImage = 1 /*close icon*/ : iImage = 0 ; /*open icon*/
}
else
iImage = 2 ; //doc icon
return iImage ;
}
return 0 ;
}
//override called when OnLButtondown
void CSuperGridCtrlEx :: OnControlLButtonDown ( UINT nFlags , CPoint point , LVHITTESTINFO & ht )
{
//now I am sure I added a combobox some where, so check for this control
CTreeItem * pSelItem = GetTreeItem ( ht . iItem );
if ( pSelItem != NULL )
{
CItemInfo * pInfo = GetData ( pSelItem );
CItemInfo :: CONTROLTYPE ctrlType ;
if ( pInfo -> GetControlType ( ht . iSubItem - 1 , ctrlType ))
{
if ( ctrlType == CItemInfo :: combobox )
{
if ( this -> m_bEditStyle && pSelItem -> m_bCanEditMe )
{
CStringList * list = NULL ;
pInfo -> GetListData ( ht . iSubItem - 1 , list );
CComboBox * pList = ShowList ( ht . iItem , ht . iSubItem , list );
}
}
}
else
{
if ( this -> m_bEditStyle && pSelItem -> m_bCanEditMe )
{
CSuperGridCtrl :: OnControlLButtonDown ( nFlags , point , ht );
}
}
}
}
BOOL CSuperGridCtrlEx :: OnVkReturn ()
{
BOOL bResult = FALSE ;
int iItem = GetNextItem ( - 1 , LVNI_ALL | LVNI_SELECTED );
if ( GetCurSubItem () != - 1 && iItem != - 1 )
{
CTreeItem * pSelItem = GetTreeItem ( iItem );
if ( pSelItem != NULL )
{
CHeaderCtrl * pHeader = ( CHeaderCtrl * ) GetDlgItem ( 0 );
int iSubItem = Header_OrderToIndex ( pHeader -> m_hWnd , GetCurSubItem ());
CItemInfo * pInfo = GetData ( pSelItem );
CItemInfo :: CONTROLTYPE ctrlType ;
if ( pInfo -> GetControlType ( iSubItem - 1 , ctrlType ))
{
switch ( ctrlType )
{
/*put in your own control here*/
case CItemInfo :: datecontrol : break ;
case CItemInfo :: spinbutton : break ;
case CItemInfo :: dropdownlistviewwhatevercontrol : break ;
case CItemInfo :: combobox :
{
CStringList * list = NULL ;
pInfo -> GetListData ( iSubItem - 1 , list );
CComboBox * pList = ShowList ( iItem , iSubItem , list );
bResult = TRUE ; //I'll handle it from here
} break ;
default : break ;
}
}
}
}
return bResult ;
}
#define IDC_COMBOBOXINLISTVIEW 0x1235
CComboBox * CSuperGridCtrlEx :: ShowList ( int nItem , int nCol , CStringList * lstItems )
{
CString strFind = GetItemText ( nItem , nCol );
//basic code start
CRect rect ;
int offset = 0 ;
// Make sure that the item is visible
if ( ! EnsureVisible ( nItem , TRUE )) return NULL ;
GetSubItemRect ( nItem , nCol , LVIR_BOUNDS , rect );
// Now scroll if we need to expose the column
CRect rcClient ;
GetClientRect ( rcClient );
if ( offset + rect . left < 0 || offset + rect . left > rcClient . right )
{
CSize size ;
size . cx = offset + rect . left ;
size . cy = 0 ;
Scroll ( size );
rect . left -= size . cx ;
}
rect . left += offset ;
rect . right = rect . left + GetColumnWidth ( nCol );
if ( rect . right > rcClient . right )
rect . right = rcClient . right ;
//basic code end
rect . bottom += 10 * rect . Height (); //dropdown area
DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | CBS_DROPDOWNLIST ;
CComboBox * pList = new CComboInListView ( nItem , nCol , lstItems );
pList -> Create ( dwStyle , rect , this , IDC_COMBOBOXINLISTVIEW );
pList -> ModifyStyleEx ( 0 , WS_EX_CLIENTEDGE ); //can we tell at all
pList -> SetHorizontalExtent ( CalcHorzExtent ( pList , lstItems ));
pList -> ShowDropDown ();
pList -> SelectString ( - 1 , strFind . GetBuffer ( 1 ));
// The returned pointer should not be saved
return pList ;
}
int CSuperGridCtrlEx :: CalcHorzExtent ( CWnd * pWnd , CStringList * pList )
{
int nExtent = 0 ;
if ( pWnd != NULL )
{
CDC * pDC = pWnd -> GetDC ();
HFONT hFont = ( HFONT ) pWnd -> SendMessage ( WM_GETFONT ); //why not pWnd->GetFont();..I like the send thing alot and
CFont * pFont = CFont :: FromHandle ( hFont ); //this way I get to use this function..cool :)
if ( pFont != NULL ) //ya what ever makes me happy,.right :}
{
CFont * pOldFont = pDC -> SelectObject ( pFont );
CSize newExtent ;
POSITION pos = pList -> GetHeadPosition ();
while ( pos != NULL )
{
CString str ( pList -> GetNext ( pos ));
newExtent = pDC -> GetTextExtent ( str );
newExtent . cx += 6 ;
if ( newExtent . cx > nExtent )
{
nExtent = newExtent . cx ;
}
}
pDC -> SelectObject ( pOldFont );
}
pWnd -> ReleaseDC ( pDC );
}
return nExtent ;
}
CTreeItem * CSuperGridCtrlEx :: Search ( CString strItem ,...)
{
if ( ! GetItemCount ())
return NULL ;
va_list args ;
va_start ( args , strItem );
int nCount = 0 ;
for (;;)
{
LPCTSTR lpsz = va_arg ( args , LPCTSTR );
if ( lpsz == NULL )
break ;
nCount ++ ;
}
POSITION pos = GetRootHeadPosition ();
while ( pos != NULL )
{
CTreeItem * pParent = ( CTreeItem * ) GetNextRoot ( pos );
CTreeItem * pItem = pParent ;
CItemInfo * lp = GetData ( pParent );
CString strData = lp -> GetItemText ();
if ( strData == strItem ) //must be a match before going further...suit you self
{
va_start ( args , strItem );
int nResult = 0 ;
for ( int i = 0 ; i < nCount ; i ++ )
{
LPCTSTR lpsz = va_arg ( args , LPCTSTR );
for ( int nCol = 0 ; nCol < lp -> GetItemCount (); nCol ++ )
{
CString str = lp -> GetSubItem ( nCol );
if ( ! str . CompareNoCase ( lpsz ))
{
nResult ++ ;
break ;
}
}
}
va_end ( args );
if ( nCount == nResult ) //all args was found return node
return pParent ;
}
//GetNext ....loop through all children
for (;;)
{
CTreeItem * pCur = GetNext ( pParent , pItem , TRUE , FALSE /*regardless of the item are hidden or not, set to TRUE if only visible items must be included in the search*/ );
if ( ! IsChildOf ( pParent , pCur ))
break ;
else
if ( pCur == pItem )
break ;
CItemInfo * lp = GetData ( pCur );
CString strData = lp -> GetItemText ();
if ( strData == strItem ) //must be a match before going further
{
va_start ( args , strItem );
int nResult = 0 ;
for ( int i = 0 ; i < nCount ; i ++ )
{
LPCTSTR lpsz = va_arg ( args , LPCTSTR );
for ( int nCol = 0 ; nCol < lp -> GetItemCount (); nCol ++ )
{
CString str = lp -> GetSubItem ( nCol );
if ( ! str . CompareNoCase ( lpsz ))
{
nResult ++ ;
break ;
}
}
}
va_end ( args );
if ( nCount == nResult ) //all args was found return node
return pCur ;
}
pItem = pCur ; //next;
}
}
return NULL ;
}
void CSuperGridCtrlEx :: SortData ()
{
int nIndex = GetNextItem ( - 1 , LVNI_ALL | LVNI_SELECTED );
if ( nIndex ==- 1 )
return ;
CTreeItem * pItem = reinterpret_cast < CTreeItem *> ( GetItemData ( nIndex ));
if ( AfxMessageBox ( _T ( "Sort all children(Yes) \n or just sort rootitems(No)" ), MB_YESNO ) == IDYES )
Sort ( pItem , TRUE );
else
Sort ( pItem , FALSE );
//do a simple refresh thing
if ( ItemHasChildren ( pItem ))
{
SetRedraw ( 0 );
Collapse ( pItem );
Expand ( pItem , nIndex );
SetRedraw ( 1 );
}
}
//another search thing
CTreeItem * CSuperGridCtrlEx :: SearchEx ( CTreeItem * pStartPosition , CString strItem )
{
CItemInfo * lp = GetData ( pStartPosition );
//if(lp->GetCheck()) another condition here maybe
CString strData = lp -> GetItemText ();
if ( strData == strItem )
{
return pStartPosition ;
}
const int nChildren = NumChildren ( pStartPosition );
if ( nChildren > 0 )
{
POSITION pos = GetHeadPosition ( pStartPosition );
while ( pos )
{
CTreeItem * pChild = GetNextChild ( pStartPosition , pos );
CItemInfo * lp = GetData ( pChild );
CString strData = lp -> GetItemText ();
if ( strData == strItem )
{
return pChild ;
}
}
}
POSITION pos = GetHeadPosition ( pStartPosition );
while ( pos )
{
CTreeItem * pChild = GetNextChild ( pStartPosition , pos );
CItemInfo * lp = GetData ( pChild );
CString strData = lp -> GetItemText ();
if ( strData == strItem )
{
return pChild ;
}
pChild = SearchEx ( pChild , strItem );
if ( pChild != NULL )
return pChild ;
}
return NULL ;
}
BOOL CSuperGridCtrlEx :: OnDeleteItem ( CTreeItem * pItem , int nIndex )
{
return 1 ;
}
BOOL CSuperGridCtrlEx :: OnItemExpanding ( CTreeItem * pItem , int iItem )
{
return 1 ;
}
BOOL CSuperGridCtrlEx :: OnItemExpanded ( CTreeItem * pItem , int iItem )
{
return 1 ;
}
BOOL CSuperGridCtrlEx :: OnCollapsing ( CTreeItem * pItem )
{
return 1 ;
}
BOOL CSuperGridCtrlEx :: OnItemCollapsed ( CTreeItem * pItem )
{
return 1 ;
}
CImageList * CSuperGridCtrlEx :: CreateDragImageEx ( int nItem )
{
if ( m_bDrag )
return CSuperGridCtrl :: CreateDragImageEx ( GetDragItem ());
else
return NULL ;
}