📄 draglistctrl.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 + -