123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- /////////////////////////////////////////////////////////////////////////////
- // DragDropListCtrl.cpp : implementation file
- //
- // Adrian Stanley 13/02/2000
- // Totally free source code - use however you like.
- // adrian@adrians.demon.co.uk.
- //
- // This class illustrates how to implement drag and drop for a MFC
- // list control.
- //
- // It has the following features:
- // Supports dragging of single and multiple selections.
- // Potential drag targets are highlighted (selected) as the mouse moves
- // over them.
- // The list box will scroll when you try to drag out of the top or bottom.
- // Horizontal mouse movement is ignored; if the mouse is to the left or right
- // of the list control, dragging still occurs as though the mouse is over
- // the control.
- // Works with LVS_EX_FULLROWSELECT style on or off.
- // Preserves checked state of dragged items.
- // All code encapulated in the control - no changes required to parent
- // class.
- /////////////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "DragDropListCtrl.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- static const int SCROLL_TIMER_ID = 1;
- ////////////////////////////////////////////////////////////////////////////
- CDragDropListCtrl::CDragDropListCtrl() :
- m_nDropIndex(-1),
- m_pDragImage(NULL),
- m_nPrevDropIndex(-1),
- m_uPrevDropState(NULL),
- m_uScrollTimer(0),
- m_ScrollDirection(scrollNull),
- m_dwStyle(NULL),
- m_nCurIndex(-1)
- {
- }
- CDragDropListCtrl::~CDragDropListCtrl()
- {
- // Fail safe clean up.
- delete m_pDragImage;
- m_pDragImage = NULL;
- KillScrollTimer();
- }
- BEGIN_MESSAGE_MAP(CDragDropListCtrl, CListCtrl)
- ON_WM_MOUSEMOVE()
- ON_WM_LBUTTONUP()
- ON_NOTIFY_REFLECT(LVN_BEGINDRAG, OnBeginDrag)
- ON_WM_TIMER()
- END_MESSAGE_MAP()
- // MFC控件事件函数-拖动时产生的事件;
- void CDragDropListCtrl::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
- {
- NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
- if (pNMListView)
- {
- m_nPrevDropIndex = -1;
- m_uPrevDropState = NULL;
-
- // Items being dragged - can be one or more.
- // 可以拖动一个或多个子项;
- m_anDragIndexes.RemoveAll(); // 清空数组,重新添加被选中的拖动的项索引;
- POSITION pos = GetFirstSelectedItemPosition();
- while (pos)
- {
- m_anDragIndexes.Add(GetNextSelectedItem(pos));
- }
- // 获取当前控件的模式;
- DWORD dwStyle = GetStyle();
- // 如果是单选,设置为多选样式以使能够拖动时能多个图标一起移动;
- if ((dwStyle & LVS_SINGLESEL) == LVS_SINGLESEL)
- {
- // List control is single select; we need it to be multi-select so
- // we can show both the drag item and potential drag target as selected.
- m_dwStyle = dwStyle;
- ModifyStyle(LVS_SINGLESEL, NULL);
- }
- // 如果选中的即将被拖动的项索引数不为0;
- if (m_anDragIndexes.GetSize() > 0)
- {
- // Create a drag image from the centre point of the item image.
- // Clean up any existing drag image first.
- // 清空所有之前存在的拖动图标,并以当前项中心点重新创建一个拖动图标;
- delete m_pDragImage;
- CPoint ptDragItem;
- // 创建新的拖动图标;
- m_pDragImage = CreateDragImageEx(&ptDragItem);
- if (m_pDragImage)
- {
- m_pDragImage->BeginDrag(0, ptDragItem);
- //m_pDragImage->DragEnter(CWnd::GetDesktopWindow(), pNMListView->ptAction);
- m_pDragImage->DragEnter(GetParent(), pNMListView->ptAction);
-
- // Capture all mouse messages in case the user drags outside the control.
- // 设置当前线程窗口捕获鼠标;
- SetCapture();
- }
- }
- }
-
- *pResult = 0;
- }
- // Based on code by Frank Kobs.
- CImageList* CDragDropListCtrl::CreateDragImageEx(LPPOINT lpPoint)
- {
- // 单个项时的矩形;
- CRect rectSingle;
- // 所有项并集后的矩形大小;
- CRect rectComplete(0, 0, 0, 0);
- // 选中项的索引;
- int nIndex = -1;
- // 是否初始化并集矩形变量;
- BOOL bFirst = TRUE;
- // Determine the size of the drag image.
- // 确定拖动图标的大小;
- POSITION pos = GetFirstSelectedItemPosition();
- while (pos)
- {
- nIndex = GetNextSelectedItem(pos);
- GetItemRect(nIndex, rectSingle, LVIR_BOUNDS);
- if (bFirst)
- {
- // Initialize the CompleteRect
- // 初始化并集矩形变量;
- GetItemRect(nIndex, rectComplete, LVIR_BOUNDS);
- bFirst = FALSE;
- }
- // 并集每一个项的大小;
- rectComplete.UnionRect(rectComplete, rectSingle);
- }
- // Create bitmap in memory DC
- // 获取当前客户区域DC句柄;
- CClientDC dcClient(this);
- CDC dcMem;
- CBitmap Bitmap;
- // 创建兼容内存位图DC;
- if (!dcMem.CreateCompatibleDC(&dcClient))
- {
- return NULL;
- }
- // 在DC上创建兼容位图;
- if (!Bitmap.CreateCompatibleBitmap(&dcClient, rectComplete.Width(), rectComplete.Height()))
- {
- return NULL;
- }
-
- // 保存DC上创建的兼容位图;
- CBitmap* pOldMemDCBitmap = dcMem.SelectObject(&Bitmap);
-
- // Here green is used as mask color.
- // 用绿色作为屏蔽色;
- dcMem.FillSolidRect(0, 0, rectComplete.Width(), rectComplete.Height(), RGB(0, 255, 0));
- // Paint each DragImage in the DC.
- // 在DC环境上画出每一个项的拖动图标;
- CImageList* pSingleImageList = NULL;
- CPoint pt;
- pos = GetFirstSelectedItemPosition();
- while (pos)
- {
- nIndex = GetNextSelectedItem(pos);
- GetItemRect(nIndex, rectSingle, LVIR_BOUNDS);
- // 为每一个项创建拖动图标;
- pSingleImageList = CreateDragImage(nIndex, &pt);
- if (pSingleImageList)
- {
- // Make sure width takes into account not using LVS_EX_FULLROWSELECT style.
- IMAGEINFO ImageInfo;
- // 获取每个项的图标信息;
- pSingleImageList->GetImageInfo(0, &ImageInfo);
- rectSingle.right = rectSingle.left + (ImageInfo.rcImage.right - ImageInfo.rcImage.left);
- // 合并所有拖动图标并在并集矩形内重绘;
- pSingleImageList->DrawIndirect(
- &dcMem,
- 0,
- CPoint(rectSingle.left - rectComplete.left,
- rectSingle.top - rectComplete.top),
- rectSingle.Size(),
- CPoint(0,0));
- // 释放内存;
- delete pSingleImageList;
- }
- }
- dcMem.SelectObject(pOldMemDCBitmap);
- // Create the imagelist with the merged drag images.
- // 用合并后的拖动图标矩形创建一个ImageList对象;
- CImageList* pCompleteImageList = new CImageList;
-
- pCompleteImageList->Create(rectComplete.Width(), rectComplete.Height(), ILC_COLOR | ILC_MASK, 0, 1);
- // Here green is used as mask color.
- pCompleteImageList->Add(&Bitmap, RGB(0, 255, 0));
- Bitmap.DeleteObject();
- // As an optional service:
- // Find the offset of the current mouse cursor to the imagelist
- // this we can use in BeginDrag().
- if (lpPoint)
- {
- CPoint ptCursor;
- GetCursorPos(&ptCursor);
- ScreenToClient(&ptCursor);
- lpPoint->x = ptCursor.x - rectComplete.left;
- lpPoint->y = ptCursor.y - rectComplete.top;
- }
- return pCompleteImageList;
- }
- void CDragDropListCtrl::OnMouseMove(UINT nFlags, CPoint point)
- {
- if (m_pDragImage)
- {
- // Must be dragging, as there is a drag image.
- // Move the drag image.
- // 移动拖动图标;
- CPoint ptDragImage(point);
- ClientToScreen(&ptDragImage);
- m_pDragImage->DragMove(ptDragImage);
-
- // Leave dragging so we can update potential drop target selection.
- // 去除DragLeave函数,在拖动时就不会闪烁了;
- //m_pDragImage->DragLeave(CWnd::GetDesktopWindow());
- //m_pDragImage->DragLeave(GetParent());
- // Force x coordinate to always be in list control - only interested in y coordinate.
- // In effect the list control has captured all horizontal mouse movement.
- static const int nXOffset = 8;
- CRect rect;
- GetWindowRect(rect);
- // 获取移动中鼠标下方的窗口句柄;
- CWnd* pDropWnd = CWnd::WindowFromPoint(CPoint(rect.left + nXOffset, ptDragImage.y));
- // Get the window under the drop point.
- if (pDropWnd == this)
- {
- // Still in list control so select item under mouse as potential drop target.
- // 如果点仍在CListCtrl控件内,更新拖动图标的位置;
- point.x = nXOffset; // Ensures x coordinate is always valid.
- UpdateSelection(HitTest(point));
- }
- // 获取控件的客户区域;
- CRect rectClient;
- GetClientRect(rectClient);
- // 获取拖动图标的坐标点;
- CPoint ptClientDragImage(ptDragImage);
- ScreenToClient(&ptClientDragImage);
- // Client rect includes header height, so ignore it, i.e.,
- // moving the mouse over the header (and higher) will result in a scroll up.
- CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
- if (pHeader)
- {
- CRect rectHeader;
- pHeader->GetClientRect(rectHeader);
- rectClient.top += rectHeader.Height();
- }
- if (ptClientDragImage.y < rectClient.top)
- {
- // Mouse is above the list control - scroll up.
- SetScrollTimer(scrollUp);
- }
- else if (ptClientDragImage.y > rectClient.bottom)
- {
- // Mouse is below the list control - scroll down.
- SetScrollTimer(scrollDown);
- }
- else
- {
- KillScrollTimer();
- }
- // Resume dragging.
- //m_pDragImage->DragEnter(CWnd::GetDesktopWindow(), ptDragImage);
- m_pDragImage->DragEnter(GetParent(), ptDragImage);
- }
- else
- {
- KillScrollTimer();
- }
- CListCtrl::OnMouseMove(nFlags, point);
- }
- void CDragDropListCtrl::UpdateSelection(int nDropIndex)
- {
- if (nDropIndex > -1 && nDropIndex < GetItemCount())
- {
- // Drop index is valid and has changed since last mouse movement.
- RestorePrevDropItemState();
- // Save information about current potential drop target for restoring next time round.
- m_nPrevDropIndex = nDropIndex;
- m_uPrevDropState = GetItemState(nDropIndex, LVIS_SELECTED);
- // Select current potential drop target.
- SetItemState(nDropIndex, LVIS_SELECTED, LVIS_SELECTED);
- m_nDropIndex = nDropIndex; // Used by DropItem().
- UpdateWindow();
- }
- }
- void CDragDropListCtrl::RestorePrevDropItemState()
- {
- if (m_nPrevDropIndex > -1 && m_nPrevDropIndex < GetItemCount())
- {
- // Restore state of previous potential drop target.
- SetItemState(m_nPrevDropIndex, m_uPrevDropState, LVIS_SELECTED);
- }
- }
- void CDragDropListCtrl::SetScrollTimer(EScrollDirection ScrollDirection)
- {
- if (m_uScrollTimer == 0)
- {
- m_uScrollTimer = SetTimer(SCROLL_TIMER_ID, 100, NULL);
- }
- m_ScrollDirection = ScrollDirection;
- }
- void CDragDropListCtrl::KillScrollTimer()
- {
- if (m_uScrollTimer != 0)
- {
- KillTimer(SCROLL_TIMER_ID);
- m_uScrollTimer = 0;
- m_ScrollDirection = scrollNull;
- }
- }
- void CDragDropListCtrl::OnLButtonUp(UINT nFlags, CPoint point)
- {
- if (m_pDragImage)
- {
- KillScrollTimer();
- // Release the mouse capture and end the dragging.
- // 释放对窗口鼠标的捕获;
- ::ReleaseCapture();
- //m_pDragImage->DragLeave(CWnd::GetDesktopWindow());
- m_pDragImage->DragLeave(GetParent());
- m_pDragImage->EndDrag();
- m_pDragImage->DeleteImageList();
- delete m_pDragImage;
- m_pDragImage = NULL;
- // Drop the item on the list.
- DropItem(point);
- }
-
- CListCtrl::OnLButtonUp(nFlags, point);
- }
- void CDragDropListCtrl::DropItem()
- {
- RestorePrevDropItemState();
- // Drop after currently selected item.
- // 删除当前选中的项;
- m_nDropIndex++;
- if (m_nDropIndex < 0 || m_nDropIndex > GetItemCount() - 1)
- {
- // Fail safe - invalid drop index, so drop at end of list.
- m_nDropIndex = GetItemCount();
- }// 从尾部开始;
- int nColumns = 1;
- CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
- if (pHeader)
- {
- nColumns = pHeader->GetItemCount();
- }
- // Move all dragged items to their new positions.
- // 将所有拖动项移动到新位置;
- for (int nDragItem = 0; nDragItem < m_anDragIndexes.GetSize(); nDragItem++)
- {
- // 获取拖动项的索引;
- int nDragIndex = m_anDragIndexes[nDragItem];
- if (nDragIndex > -1 && nDragIndex < GetItemCount())
- {
- // Get information about this drag item.
- // 获取指定索引位置的拖动项的信息,LV_ITEM必须指定iItem值,才能GetItem获取mask标识的其他项信息;
- // 同时,这属于一个GetItem的使用示例;
- char szText[256];
- LV_ITEM lvItem;
- ZeroMemory(&lvItem, sizeof(LV_ITEM));
- lvItem.iItem = nDragIndex;
- lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
- lvItem.stateMask = LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED | LVIS_STATEIMAGEMASK;
- lvItem.pszText = szText;
- lvItem.cchTextMax = sizeof(szText) - 1;
- GetItem(&lvItem);
- BOOL bChecked = GetCheck(nDragIndex);
-
- // Before moving drag item, make sure it is deselected in its original location,
- // otherwise GetSelectedCount() will return 1 too many.
- SetItemState(nDragIndex, static_cast<UINT>(~LVIS_SELECTED), LVIS_SELECTED);
- // Insert the dragged item at drop index.
- // 重新赋值iItem,将拖动项插入到删除索引位置上(起始时m_nDropIndex为最后项索引);
- lvItem.iItem = m_nDropIndex;
- InsertItem(&lvItem);
- if (bChecked)
- {
- SetCheck(m_nDropIndex);
- }
-
- // Index of dragged item will change if item has been dropped above itself.
- if (nDragIndex > m_nDropIndex)
- {
- nDragIndex++;
- }
- // Fill in all the columns for the dragged item.
- // 填充所有拖动项的列信息(子项中的文字);
- lvItem.mask = LVIF_TEXT;
- lvItem.iItem = m_nDropIndex;
- for (int nColumn = 1; nColumn < nColumns; nColumn++)
- {
- _tcscpy(lvItem.pszText, (LPCTSTR)(GetItemText(nDragIndex, nColumn)));
- lvItem.iSubItem = nColumn;
- SetItem(&lvItem);
- }
-
- // Delete the original item.
- // 删除原始项;
- DeleteItem(nDragIndex);
- // Need to adjust indexes of remaining drag items.
- for (int nNewDragItem = nDragItem; nNewDragItem < m_anDragIndexes.GetSize(); nNewDragItem++)
- {
- int nNewDragIndex = m_anDragIndexes[nNewDragItem];
- if (nDragIndex < nNewDragIndex && nNewDragIndex < m_nDropIndex)
- {
- // Item has been removed from above this item, and inserted after it,
- // so this item moves up the list.
- m_anDragIndexes[nNewDragItem] = max(nNewDragIndex - 1, 0);
- }
- else if (nDragIndex > nNewDragIndex && nNewDragIndex > m_nDropIndex)
- {
- // Item has been removed from below this item, and inserted before it,
- // so this item moves down the list.
- m_anDragIndexes[nNewDragItem] = nNewDragIndex + 1;
- }
- }
- if (nDragIndex > m_nDropIndex)
- {
- // Item has been added before the drop target, so drop target moves down the list.
- m_nDropIndex++;
- }
- }
- }
- if (m_dwStyle != NULL)
- {
- // Style was modified, so return it back to original style.
- ModifyStyle(NULL, m_dwStyle);
- m_dwStyle = NULL;
- }
- }
- void CDragDropListCtrl::OnTimer(UINT nIDEvent)
- {
- if (nIDEvent == SCROLL_TIMER_ID && m_pDragImage)
- {
- WPARAM wParam = NULL;
- int nDropIndex = -1;
- if (m_ScrollDirection == scrollUp)
- {
- wParam = MAKEWPARAM(SB_LINEUP, 0);
- nDropIndex = m_nDropIndex - 1;
- }
- else if (m_ScrollDirection == scrollDown)
- {
- wParam = MAKEWPARAM(SB_LINEDOWN, 0);
- nDropIndex = m_nDropIndex + 1;
- }
- m_pDragImage->DragShowNolock(FALSE);
- SendMessage(WM_VSCROLL, wParam, NULL);
- UpdateSelection(nDropIndex);
- m_pDragImage->DragShowNolock(TRUE);
- }
- else
- {
- CListCtrl::OnTimer(nIDEvent);
- }
- }
- int CDragDropListCtrl::GetPtItemIndex(CPoint pt)
- {
- // 判断点是否还在控件内;
- // CWnd* pDropWnd = CWnd::WindowFromPoint(pt);
- // if (pDropWnd != this)
- // {
- // AfxMessageBox(_T("不在控件上"));
- // return -1;
- // }
- // 遍历全部项,查找点在哪个项上;
- CRect rtItem;
- int nCount = GetItemCount();
- int nIndex = 0;
- for (nIndex = 0; nIndex < nCount; nIndex++)
- {
- GetItemRect(nIndex, &rtItem, LVIR_BOUNDS);//LVIR_ICON
- if ( PtInRect(rtItem,pt) )
- break;
- }
- // 返回项索引值;
- return (nIndex == nCount) ? -1 : nIndex;
- }
- void CDragDropListCtrl::DropItem(CPoint pt)
- {
- RestorePrevDropItemState();
- // 获取点对应的项值;
- m_nCurIndex = GetPtItemIndex(pt);
- #if 0
- CString strIndex;
- strIndex.Format(_T("%d~%d"), m_anDragIndexes[0], m_nCurIndex);
- AfxMessageBox(strIndex);
- #endif
- if(m_nCurIndex == -1)
- return;
- // 相等时,不处理;
- if (m_nCurIndex > m_anDragIndexes[0])// 拖动项往后拖;
- {
- /*
- int nColumns = 1;
- CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
- if (pHeader)
- nColumns = pHeader->GetItemCount();
- int nDragIndex = m_anDragIndexes[0];
- // 获取指定索引位置的拖动项的信息,LV_ITEM必须指定iItem值,才能GetItem获取mask标识的其他项信息;
- // 同时,这属于一个GetItem的使用示例;
- char szText[256] = {0};
- LV_ITEM lvItem;
- ZeroMemory(&lvItem, sizeof(LV_ITEM));
- lvItem.iItem = nDragIndex;
- lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
- lvItem.stateMask = LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED | LVIS_STATEIMAGEMASK;
- lvItem.pszText = szText;
- lvItem.cchTextMax = sizeof(szText) - 1;
- GetItem(&lvItem);
- BOOL bChecked = GetCheck(nDragIndex);
-
- SetItemState(nDragIndex, static_cast<UINT>(~LVIS_SELECTED), LVIS_SELECTED);
- // Insert the dragged item at drop index.
- // 重新赋值iItem,将拖动项插入到删除索引位置上(起始时m_nDropIndex为最后项索引);
- lvItem.iItem = m_nDropIndex;
- InsertItem(&lvItem);
- if (bChecked)
- {
- SetCheck(m_nDropIndex);
- }
- // Index of dragged item will change if item has been dropped above itself.
- if (nDragIndex > m_nDropIndex)
- nDragIndex++;
- // Fill in all the columns for the dragged item.
- // 填充所有拖动项的列信息(子项中的文字);
- lvItem.mask = LVIF_TEXT;
- lvItem.iItem = m_nDropIndex;
- for (int nColumn = 1; nColumn < nColumns; nColumn++)
- {
- _tcscpy(lvItem.pszText, (LPCTSTR)(GetItemText(nDragIndex, nColumn)));
- lvItem.iSubItem = nColumn;
- SetItem(&lvItem);
- }
- // Delete the original item.
- // 删除原始项;
- DeleteItem(nDragIndex);
- */
- }
- else if (m_nCurIndex < m_anDragIndexes[0])// 拖动项往前拖;
- {
-
- }
- #if 0
- // Drop after currently selected item.
- // 删除当前选中的项;
- m_nDropIndex++;
- if (m_nDropIndex < 0 || m_nDropIndex > GetItemCount() - 1)
- {
- // Fail safe - invalid drop index, so drop at end of list.
- m_nDropIndex = GetItemCount();
- }// 从尾部开始;
- int nColumns = 1;
- CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
- if (pHeader)
- {
- nColumns = pHeader->GetItemCount();
- }
- // Move all dragged items to their new positions.
- // 将所有拖动项移动到新位置;
- for (int nDragItem = 0; nDragItem < m_anDragIndexes.GetSize(); nDragItem++)
- {
- // 获取拖动项的索引;
- int nDragIndex = m_anDragIndexes[nDragItem];
- if (nDragIndex > -1 && nDragIndex < GetItemCount())
- {
- // Get information about this drag item.
- // 获取指定索引位置的拖动项的信息,LV_ITEM必须指定iItem值,才能GetItem获取mask标识的其他项信息;
- // 同时,这属于一个GetItem的使用示例;
- char szText[256];
- LV_ITEM lvItem;
- ZeroMemory(&lvItem, sizeof(LV_ITEM));
- lvItem.iItem = nDragIndex;
- lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE | LVIF_PARAM;
- lvItem.stateMask = LVIS_DROPHILITED | LVIS_FOCUSED | LVIS_SELECTED | LVIS_STATEIMAGEMASK;
- lvItem.pszText = szText;
- lvItem.cchTextMax = sizeof(szText) - 1;
- GetItem(&lvItem);
- BOOL bChecked = GetCheck(nDragIndex);
- // Before moving drag item, make sure it is deselected in its original location,
- // otherwise GetSelectedCount() will return 1 too many.
- SetItemState(nDragIndex, static_cast<UINT>(~LVIS_SELECTED), LVIS_SELECTED);
- // Insert the dragged item at drop index.
- // 重新赋值iItem,将拖动项插入到删除索引位置上(起始时m_nDropIndex为最后项索引);
- lvItem.iItem = m_nDropIndex;
- InsertItem(&lvItem);
- if (bChecked)
- {
- SetCheck(m_nDropIndex);
- }
- // Index of dragged item will change if item has been dropped above itself.
- if (nDragIndex > m_nDropIndex)
- {
- nDragIndex++;
- }
- // Fill in all the columns for the dragged item.
- // 填充所有拖动项的列信息(子项中的文字);
- lvItem.mask = LVIF_TEXT;
- lvItem.iItem = m_nDropIndex;
- for (int nColumn = 1; nColumn < nColumns; nColumn++)
- {
- _tcscpy(lvItem.pszText, (LPCTSTR)(GetItemText(nDragIndex, nColumn)));
- lvItem.iSubItem = nColumn;
- SetItem(&lvItem);
- }
- // Delete the original item.
- // 删除原始项;
- DeleteItem(nDragIndex);
- // Need to adjust indexes of remaining drag items.
- for (int nNewDragItem = nDragItem; nNewDragItem < m_anDragIndexes.GetSize(); nNewDragItem++)
- {
- int nNewDragIndex = m_anDragIndexes[nNewDragItem];
- if (nDragIndex < nNewDragIndex && nNewDragIndex < m_nDropIndex)
- {
- // Item has been removed from above this item, and inserted after it,
- // so this item moves up the list.
- m_anDragIndexes[nNewDragItem] = max(nNewDragIndex - 1, 0);
- }
- else if (nDragIndex > nNewDragIndex && nNewDragIndex > m_nDropIndex)
- {
- // Item has been removed from below this item, and inserted before it,
- // so this item moves down the list.
- m_anDragIndexes[nNewDragItem] = nNewDragIndex + 1;
- }
- }
- if (nDragIndex > m_nDropIndex)
- {
- // Item has been added before the drop target, so drop target moves down the list.
- m_nDropIndex++;
- }
- }
- }
- if (m_dwStyle != NULL)
- {
- // Style was modified, so return it back to original style.
- ModifyStyle(NULL, m_dwStyle);
- m_dwStyle = NULL;
- }
- #endif
- }
|