// SortList1.cpp : implementation file // #include "stdafx.h" #include "SortList.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CSortList CSortList::CSortList() { m_bDragging = FALSE; m_bReSort = false; //每次拖动后不需要重排 m_lCheck1 = -1; m_lCheck2 = -1; m_lCheck3 = -1; } CSortList::~CSortList() { } BEGIN_MESSAGE_MAP(CSortList, CListCtrl) //{{AFX_MSG_MAP(CSortList) ON_WM_LBUTTONUP() ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBegindrag) ON_WM_MOUSEMOVE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSortList message handlers void CSortList::Init(BOOL bReSort , long lCheck1 , long lCheck2 , long lCheck3) { //ListView_SetExtendedListViewStyle(m_hWnd, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP|LVS_EX_CHECKBOXES); this->SetExtendedStyle(LVS_EX_TRACKSELECT|LVS_EX_ONECLICKACTIVATE|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_HEADERDRAGDROP|LVS_EX_CHECKBOXES); m_bReSort = bReSort; //每次拖动后是否需要重排 m_lCheck1 = lCheck1; //每次必选的项目 m_lCheck2 = lCheck2; //每次必选的项目 m_lCheck3 = lCheck3; //每次必选的项目 } void CSortList::OnLButtonUp(UINT nFlags, CPoint point) { if( m_bDragging ) { //RELEASE THE MOUSE CAPTURE AND END THE DRAGGING ::ReleaseCapture(); m_bDragging = FALSE; m_pDragImage->DragLeave(GetDesktopWindow()); m_pDragImage->EndDrag(); delete m_pDragImage; //GET THE WINDOW UNDER THE DROP POINT CPoint pt(point); ClientToScreen(&pt); m_pDropWnd = WindowFromPoint(pt); //DROP THE ITEM ON THE LIST if( m_pDropWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)) ) DropItemOnList(); CListCtrl::OnLButtonUp(nFlags, point); return ; } if ( m_lCheck1 >=0 ) //每次必选 { NoverCheck(); //永远必须的一个。 } if ( m_bReSort ) //重排 { ReShowSort(); } CListCtrl::OnLButtonUp(nFlags, point); } void CSortList::DropItemOnList() { //GET THE DROP INDEX m_ptDropPoint.y += 10; m_ptDropPoint.x = 0;//allows dropping to right of last column m_nDropIndex = this->HitTest(m_ptDropPoint); //GET INFORMATION ON THE DRAGGED ITEM BY SETTING AN LV_ITEM STRUCTURE //AND THEN CALLING GetItem TO FILL IT IN TCHAR szLabel[256]; LV_ITEM lvi; ZeroMemory(&lvi, sizeof(LV_ITEM)); //lvi.mask = LVIF_TEXT | LVIF_IMAGE; lvi.mask = LVIF_TEXT; lvi.stateMask = LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED; lvi.pszText = szLabel; lvi.iItem = m_nDragIndex; lvi.cchTextMax = 255; this->GetItem(&lvi); //INSERT THE DROPPED ITEM if(m_nDropIndex < 0) m_nDropIndex = this->GetItemCount(); lvi.iItem = m_nDropIndex; this->InsertItem(&lvi); //FILL IN ALL OF THE COLUMNS CHeaderCtrl* pHeader = (CHeaderCtrl*)this->GetDlgItem(0); int nColumnCount = pHeader->GetItemCount(); lvi.mask = LVIF_TEXT; lvi.iItem = m_nDropIndex; //INDEX OF DRAGGED ITEM WILL CHANGE IF ITEM IS DROPPED ABOVE ITSELF if(m_nDragIndex > m_nDropIndex) m_nDragIndex++; for(int col=1; col < nColumnCount; col++) { _tcscpy(lvi.pszText, (LPCTSTR)(this->GetItemText(m_nDragIndex, col))); lvi.iSubItem = col; this->SetItem(&lvi); } BOOL b = this->GetCheck(m_nDragIndex); this->SetCheck( m_nDropIndex , b ); DWORD dw = this->GetItemData(m_nDragIndex); this->SetItemData( m_nDropIndex , dw ); //DELETE THE ITEM THAT WAS DRAGGED FROM ITS ORIGINAL LOCATION this->DeleteItem(m_nDragIndex); if ( m_bReSort ) //重排 { ReShowSort(); } //FIX HEADER - it disappears if item was scrolled & dropped; pHeader->RedrawWindow(); } void CSortList::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) { //NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; *pResult = 0; m_nDragIndex = ((NM_LISTVIEW *)pNMHDR)->iItem; //CREATE A DRAG IMAGE FROM THE CENTER POINT OF THE ITEM IMAGE POINT pt; pt.x = 8; pt.y = 8; m_pDragImage = this->CreateDragImage(m_nDragIndex, &pt); m_pDragImage->BeginDrag(0, CPoint (8, 8)); m_pDragImage->DragEnter( GetDesktopWindow(), ((NM_LISTVIEW *)pNMHDR)->ptAction); //SET THE FLAGS INDICATING A DRAG IN PROGRESS m_bDragging = TRUE; m_nDropIndex = -1; m_pDropWnd = this; //CAPTURE ALL MOUSE MESSAGES IN CASE THE USER DRAGS OUTSIDE OF THE VIEW SetCapture(); } void CSortList::OnMouseMove(UINT nFlags, CPoint point) { if( m_bDragging ) { m_ptDropPoint = point; ClientToScreen(&m_ptDropPoint); //MOVE THE DRAG IMAGE m_pDragImage->DragMove(m_ptDropPoint); //TEMPORARILY UNLOCK WINDOW UPDATES m_pDragImage->DragShowNolock(FALSE); //CONVERT THE DROP POINT TO CLIENT CO-ORDIANTES m_pDropWnd = WindowFromPoint(m_ptDropPoint); m_pDropWnd->ScreenToClient(&m_ptDropPoint); //SCROLL VIEW IF NECESSARY int iOverItem = this->HitTest(m_ptDropPoint); int iTopItem = this->GetTopIndex(); int iBottomItem = iTopItem + this->GetCountPerPage() - 1; if (iOverItem == iTopItem && iTopItem != 0) { this->EnsureVisible(iOverItem - 1, false); ::UpdateWindow(this->m_hWnd); } else if (iOverItem == iBottomItem && iBottomItem != (this->GetItemCount() - 1)) { this->EnsureVisible(iOverItem + 1, false); ::UpdateWindow(this->m_hWnd); } //LOCK WINDOW UPDATES m_pDragImage->DragShowNolock(TRUE); } CListCtrl::OnMouseMove(nFlags, point); } void CSortList::ReShowSort() { long lCount = this->GetItemCount(); TCHAR Buf[32]; long lIndex = 1; for ( int i=0 ; i< lCount ; i++ ) { if ( this->GetCheck(i) ) { _stprintf(Buf , _T("%d") , lIndex ); this->SetItemText( i , 0 , Buf ); lIndex ++; } else this->SetItemText( i , 0 , _T(" ") ); } } void CSortList::NoverCheck() { if ( m_lCheck1 >=0 ) //每次必选 { long lCount=this->GetItemCount(); for (int i = 0 ; i