⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 draglistctrl.cpp

📁 得到本周内的电视节目预告! f
💻 CPP
字号:
// DragListCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "DragListCtrl.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CDragListCtrl
//#define IDC_HAND            MAKEINTRESOURCE(32649)

CDragListCtrl::CDragListCtrl()
{
	m_bDragEnabled = TRUE;
	m_bDragging = FALSE;
	m_pimageListDrag = NULL;
	m_hOldCursor = NULL;

	m_iItemDrag = LB_ERR;
	m_iItemDrop = LB_ERR;
	m_lpRectLastDrop = NULL;

	m_hDraggingCursor = ::LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
	m_hDisableCursor = ::LoadCursor(NULL, MAKEINTRESOURCE(IDC_NO));
}

CDragListCtrl::~CDragListCtrl()
{
	if(m_hDraggingCursor)
		DestroyCursor(m_hDraggingCursor);
	if(m_hDisableCursor)
		DestroyCursor(m_hDisableCursor);
}


BEGIN_MESSAGE_MAP(CDragListCtrl, CListCtrl)
	//{{AFX_MSG_MAP(CDragListCtrl)
	ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBegindrag)
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDragListCtrl message handlers

void CDragListCtrl::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 
{
	if(IsDragEnabled())
	{
		CPoint          ptItem, ptAction, ptImage;
		NM_LISTVIEW     *pnmListView = (NM_LISTVIEW *)pNMHDR;

		ASSERT(!m_bDragging);
		m_bDragging = TRUE;
		m_iItemDrag = pnmListView->iItem;
		ptAction = pnmListView->ptAction;
		GetItemPosition(m_iItemDrag, &ptItem);  // ptItem is relative to (0,0) and not the view origin
		GetOrigin(&m_ptOrigin);

		ASSERT(m_pimageListDrag == NULL);
		m_pimageListDrag = CreateDragImage(m_iItemDrag, &ptImage);
		m_sizeDelta = ptAction - ptImage;   // difference between cursor pos and image pos
		m_ptHotSpot = ptAction - ptItem + m_ptOrigin;  // calculate hotspot for the cursor
		m_pimageListDrag->DragShowNolock(FALSE);  // lock updates and show drag image
		m_pimageListDrag->SetDragCursorImage(0, m_ptHotSpot);  // define the hot spot for the new cursor image
		m_pimageListDrag->BeginDrag(0, CPoint(0, 0));
		ptAction -= m_sizeDelta;
		m_pimageListDrag->DragEnter(this, ptAction);
		m_pimageListDrag->DragMove(ptAction);  // move image to overlap original icon

		m_hOldCursor = ::GetCursor();
		if(m_hDraggingCursor)
			SetCursor(m_hDraggingCursor);

		SetCapture();
	}
	
	*pResult = 0;
}

void CDragListCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	if (m_bDragging)
	{
		ASSERT(m_pimageListDrag != NULL);
		m_pimageListDrag->DragMove(point - m_sizeDelta);  // move the image
	
		CRect rcClt;
		GetDropClientRect(&rcClt);// client rect except header ctrl.

		int iItem = HitTest(point);

		if(iItem==LB_ERR && rcClt.PtInRect(point))
			iItem = GetItemCount();

		if(! OnQueryDrop(iItem))
			iItem = LB_ERR;

		if (iItem != LB_ERR)
		{
			m_iItemDrop = iItem;
			m_pimageListDrag->DragLeave(this); // unlock the window and hide drag image

			DrawDropRect(iItem);

			point -= m_sizeDelta;
			m_pimageListDrag->DragEnter(this, point);  // lock updates and show drag image
	
			if(m_hDraggingCursor)
				SetCursor(m_hDraggingCursor);
		}
		else
		{
			m_iItemDrop = LB_ERR;
			EraseDropRect();

			CSize sizeScroll(0, 0);
			if(point.y < rcClt.top)
				sizeScroll.cy = point.y - rcClt.top;
			else if(point.y > rcClt.bottom)
				sizeScroll.cy = point.y - rcClt.bottom;
			if(point.x < rcClt.left)
				sizeScroll.cx = point.x - rcClt.left;
			else if(point.x > rcClt.right)
				sizeScroll.cy = point.x - rcClt.right;

			this->Scroll(sizeScroll);

			if(m_hDisableCursor)
				SetCursor(m_hDisableCursor);
		}
	}

	CListCtrl::OnMouseMove(nFlags, point);
}

void CDragListCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
{
	OnButtonUp(point);
	CListCtrl::OnLButtonUp(nFlags, point);
}


void CDragListCtrl::OnButtonUp(CPoint point)
{
	if (m_bDragging)  // end of the drag operation
	{
		if(m_iItemDrag!=LB_ERR && m_iItemDrop!=LB_ERR)
		{
			OnEndDrag(m_iItemDrag, m_iItemDrop, point);
		}
		ClearDrag();
	}
}

void CDragListCtrl::ClearDrag()
{
	if(m_bDragging)
	{
		m_bDragging = FALSE;

		ASSERT(m_pimageListDrag != NULL);
		m_pimageListDrag->DragLeave(this);
		m_pimageListDrag->EndDrag();
		delete m_pimageListDrag;
		m_pimageListDrag = NULL;

		m_iItemDrag = LB_ERR;
		m_iItemDrop = LB_ERR;

		EraseDropRect();
		if(m_hOldCursor)
			SetCursor(m_hOldCursor);

		::ReleaseCapture();
		Invalidate();
	}
}

void CDragListCtrl::OnEndDrag(int itemDrag, int itemDrop, CPoint point)
{
	ASSERT(itemDrag>=0 && itemDrop>=0);

	if(itemDrag==itemDrop || itemDrag==itemDrop-1)
		return;
	
	DWORD dwStyle = GetStyle() & LVS_TYPEMASK;

	if (dwStyle == LVS_REPORT || dwStyle==LVS_LIST)
	{
		MoveItem(itemDrag, itemDrop);
	}

	// move the icon
	if (dwStyle == LVS_ICON || dwStyle == LVS_SMALLICON)
	{
		point -= m_ptHotSpot;  // the icon should be drawn exactly where the image is
		point += m_ptOrigin;
		SetItemPosition(m_iItemDrag, point);  // just move the dragged item
	}
}

void CDragListCtrl::CancelDragging()
{
	ClearDrag();
}

void CDragListCtrl::OnDestroy() 
{
	//If window is destroyed while dragging, we need do clearing before.
	ClearDrag();

	CListCtrl::OnDestroy();
}


void CDragListCtrl::MoveItem(int source, int dest)
{
	// save scroll pos
	int i;
	int iTopIndex = GetTopIndex();

	// save item state
	BOOL bChecked;
	LVITEM lvi;
	lvi.iItem = source;
	lvi.iSubItem = 0;
	lvi.stateMask = (UINT)-1; // retrieve all state
	lvi.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;

	GetItem(&lvi);
	bChecked = GetCheck(source);
	
	// save item's texts
	CStringArray arrTexts;
	int nCols = GetColumnCount();
	for(i=0; i< nCols; i++)
		arrTexts.Add(GetItemText(source, i));

	DeleteItem(source);
	if(dest > source)
		dest--;

	dest = InsertItem(dest,NULL);

	for(i=0; i<nCols; i++)
		SetItemText(dest, i, arrTexts[i]);

	lvi.iItem = dest;
	SetItem(&lvi);
	SetCheck(dest, bChecked);

	// restore scroll pos
	int iTopIndex2 = GetTopIndex();
	if(iTopIndex != iTopIndex2)
	{
		CRect rc1, rc2;
		GetItemRect(iTopIndex, &rc1, LVIR_BOUNDS);
		GetItemRect(iTopIndex2, &rc2, LVIR_BOUNDS);

		Scroll(CSize(0, rc1.top - rc2.top));
	}
}

int CDragListCtrl::GetColumnCount()
{
	return GetHeaderCtrl()->GetItemCount();
}

//
// show a window to indicate drop target 
//
static const CSize g_SizeDrop(1,1);

void CDragListCtrl::DrawDropRect(int iItem)
{
	ASSERT(iItem != LB_ERR);

	CRect rcItem;
	// determine the window's position
	if(iItem < GetItemCount())
	{
		GetItemRect(iItem, &rcItem, LVIR_BOUNDS);
	}
	else
	{
		GetItemRect(GetItemCount()-1, &rcItem, LVIR_BOUNDS);
		rcItem.OffsetRect(0, rcItem.Height());
	}

	CRect rcDrop(rcItem);
	rcDrop.bottom = rcDrop.top + 2;

	CRect rcClt;
	GetClientRect(&rcClt);
	rcDrop.right = rcDrop.left+rcClt.Width();

	CDC *pDC = GetDC();
	pDC->DrawDragRect(&rcDrop, g_SizeDrop, m_lpRectLastDrop, g_SizeDrop);
	ReleaseDC(pDC);

	if(! m_lpRectLastDrop)
		m_lpRectLastDrop = new CRect(rcDrop);
	else
		*m_lpRectLastDrop = rcDrop;
}

void CDragListCtrl::EraseDropRect()
{
	if(m_lpRectLastDrop)
	{
		CRect rcEmpty(0,0,0,0);

		CDC *pDC = GetDC();
		pDC->DrawDragRect(&rcEmpty, CSize(0,0), m_lpRectLastDrop, g_SizeDrop);
		ReleaseDC(pDC);

		delete m_lpRectLastDrop;
		m_lpRectLastDrop = NULL;
	}
}

void CDragListCtrl::GetDropClientRect(LPRECT lpRect)
{
	ASSERT(lpRect);
	GetClientRect(lpRect);

	CRect rcTemp;
	CHeaderCtrl *pHeaderCtrl = GetHeaderCtrl();
	if(pHeaderCtrl && pHeaderCtrl->IsWindowVisible())
	{
		pHeaderCtrl->GetWindowRect(&rcTemp);
		lpRect->top += rcTemp.Height();
	}
}


BOOL CDragListCtrl::OnQueryDrop(int iItem)
{
	return iItem!=LB_ERR? TRUE : FALSE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -