您的位置:首页 > 其它

在CListCtrl之间及CListCtrl内部实现拖放

2013-10-31 11:36 302 查看

在CListCtrl之间及CListCtrl内部实现拖放

源码下载

参考我的资源里.上传后地址还没出来,等出来后再放上



介绍

本篇文章将介绍如何实现使用拖放方法从一个CListCtrl移动项目到另一个CListCtrl,同样也显示了如何使用拖放

从在CListCtrl内部实现改变项目顺序。这是我很早就想学的一些东西,并且同样在Code Project看到很多关于这个的问题。

特别是如何在一个CListCtrl内部重排项目顺序。我希望这篇文章能回答那些问题。我很肯定还有其他方法可实现同样功能,

也许那些方法更好用,但我这个对我来说已经工作的很好了。



首先,我要先说明,网上的微软知识库有一个很好的工程例子(http://support.microsoft.com/default.aspx?scid=kb;en-us;Q148738),

它给我很大帮助。我的代码跟那个很像。那个例子说明了从CListView拖放到CTreeView。那跟我现在要介绍的有一些细微差别。不过微软

知识库的例子只给了代码,没有说明文字,尽管它有很好的注释。



同样,这篇文章假设你已经至少很熟悉如何使用CListCtrl了。在Code Project有两篇很好的文章介绍了如何使用CListCtrl和CHeadCtrl控件。

并且Chris Maunder写了一篇非常好的文章介绍使用CListCtrl的回调。如果你没有阅读过他们,请赶快阅读下哦。



概要:

Drag 和 Drop操作至少涉及以下操作步骤:

1.你处理拖放操作的通知消息(即用户点了鼠标左键,并开始拖动)

2.你必须跟踪鼠标的移动,那时用户在拖动项目。

3.最后,当鼠标按键释放时,实现实际的复制和移动动作。







对话框需要添加的成员变量:

在我们完成拖放操作时需要保存一些信息,所以我们给对话框添加一些成员变量,他们只需要实现为protected成员,因为只需要内部使用。

m_nDragIndex 是我们将要移动的CListCtrl项目索引



m_nDropIndex 是CListCtrl中鼠标将要停放的索引



m_pDragWnd 和 m_pDropWnd 是拖放涉及的CListCtrl窗口指针



m_bDragging 标识我们正在拖放操作. 在MouseMove函数中使用以便使我们知道何时跟踪



m_pDragImage 是一个CImageList对象指针. MFC使得创建和管理拖放对象的图片变得非常容易



最后需要一个数据结构保存从一个列表拖到另一个列表 (或在同一个列表当中从一个项目到另一个项目)的信息.该结构如下:

[cpp]
view plaincopyprint?

typedef struct {
LVITEM* plvi;
CString sCol2;
} lvItem, *plv

[cpp] 
view plaincopyprint?

//// 创建拖动的图片   
    POINT pt;  
    int nOffset = 10; //offset in pixels for drag image (up and 
  
                          //to the left) 
  
    pt.x = nOffset;  
    pt.y = nOffset;  
    m_pDragImage = m_listL.CreateDragImage(m_nDragIndex, &pt);  
    ASSERT(m_pDragImage); //make sure it was created
  
    //We will call delete later (in LButtonUp) to clean this up
  
    //// Change the cursor to the drag image
  
    ////    (still must perform DragMove() in OnMouseMove() to show it moving)
  
    m_pDragImage->BeginDrag(0, CPoint(nOffset, nOffset));  
    m_pDragImage->DragEnter(GetDesktopWindow(), pNMListView->ptAction);  

//// 创建拖动的图片
    POINT pt;
    int nOffset = 10; //offset in pixels for drag image (up and 
                          //to the left)
    pt.x = nOffset;
    pt.y = nOffset;
    m_pDragImage = m_listL.CreateDragImage(m_nDragIndex, &pt);
    ASSERT(m_pDragImage); //make sure it was created
    //We will call delete later (in LButtonUp) to clean this up
    //// Change the cursor to the drag image
    ////    (still must perform DragMove() in OnMouseMove() to show it moving)
    m_pDragImage->BeginDrag(0, CPoint(nOffset, nOffset));
    m_pDragImage->DragEnter(GetDesktopWindow(), pNMListView->ptAction);


第二个方法:

[cpp]
view plaincopyprint?

//// 创建拖动的图片
POINT pt;
int nOffset = -10; //offset in pixels for drag image

//(positive is up and to the left;

//neg is down and to the right)

if(m_listL.GetSelectedCount() > 1) //more than one item is selected

pt.x = nOffset;
pt.y = nOffset;
m_pDragImage = m_listL.CreateDragImage(m_nDragIndex, &pt);
ASSERT(m_pDragImage); //make sure it was created

//We will call delete later (in LButtonUp) to clean this up

CBitmap bitmap;
if(m_listL.GetSelectedCount() > 1) //more than 1 item in list is selected

//bitmap.LoadBitmap(IDB_BITMAP_MULTI);

bitmap.LoadBitmap(IDB_BITMAP_MULTI_BOXES);
else
bitmap.LoadBitmap(IDB_BITMAP_BOX);
m_pDragImage->Replace(0, &bitmap, &bitmap);
//// Change the cursor to the drag image

//// (still must perform DragMove() in OnMouseMove() to show it moving)

m_pDragImage->BeginDrag(0, CPoint(nOffset, nOffset - 4));
m_pDragImage->DragEnter(GetDesktopWindow(), pNMListView->ptAction);
然后我们设置一些成员变量的值。我们设置m_bDragging 为 TRUE,这样我们就知道开始了拖动
//// Set dragging flag and others
m_bDragging = TRUE; //we are in a drag and drop operation

m_nDropIndex = -1; //we don't have a drop index yet

m_pDragList = &m_listL; //make note of which list we are dragging from

m_pDropWnd = &m_listL; //at present the drag list is the drop list

[cpp] 
view plaincopyprint?

//// Capture all mouse messages 
  
    SetCapture ();  

//// Capture all mouse messages
    SetCapture ();






跟踪拖动过程:

使用类向导(ClassWizard),添加一个处理WM_MOUSEMOVE消息的函数。

只有在m_bDragging标记设置为TRUE时,才开始处理逻辑。

[cpp]
view plaincopyprint?

if (m_bDragging)
{

[cpp] 
view plaincopyprint?

//// Move the drag image   
        CPoint pt(point);    //get our current mouse coordinates
  
        ClientToScreen(&pt); //convert to screen coordinates
  
        m_pDragImage->DragMove(pt); //move the drag image to those coordinates
  
        // Unlock window updates (this allows the dragging image to be shown 
  
                // smoothly)   
        m_pDragImage->DragShowNolock(false);  

//// Move the drag image
        CPoint pt(point);    //get our current mouse coordinates
        ClientToScreen(&pt); //convert to screen coordinates
        m_pDragImage->DragMove(pt); //move the drag image to those coordinates
        // Unlock window updates (this allows the dragging image to be shown 
                // smoothly)
        m_pDragImage->DragShowNolock(false);




WindowFromPoint(pt)返回pt所在点的窗口。让我们知道鼠标指向哪里,他是否指向了CListCtrl窗口。



[cpp]
view plaincopyprint?

// Get the CWnd pointer of the window that is under the

// mouse cursor
CWnd* pDropWnd = WindowFromPoint (pt);
ASSERT(pDropWnd); //make sure we have a window

[cpp] 
view plaincopyprint?

//// If we drag outside current window we need 
  
                //   to adjust the highlights displayed
  
        if (pDropWnd != m_pDropWnd)  
        {  
                        //If we drag over the CListCtrl header, turn off the 
  
                        // hover highlight
  
            if (m_nDropIndex != -1)   
            {  
                TRACE("m_nDropIndex is -1/n");  
                CListCtrl* pList = (CListCtrl*)m_pDropWnd;  
                VERIFY (pList->SetItemState (m_nDropIndex, 0,   
                                                             LVIS_DROPHILITED));  
                // redraw item
  
                VERIFY (pList->RedrawItems (m_nDropIndex,   
                                                           m_nDropIndex));  
                pList->UpdateWindow ();  
                m_nDropIndex = -1;  
   }  
            else //If we drag out of the CListCtrl altogether
  
            {  
                TRACE("m_nDropIndex is not -1/n");  
                CListCtrl* pList = (CListCtrl*)m_pDropWnd;  
                int i = 0;  
                int nCount = pList->GetItemCount();  
                for(i = 0; i < nCount; i++)  
                {  
                    pList->SetItemState(i, 0, LVIS_DROPHILITED);  
                }  
                pList->RedrawItems(0, nCount);  
                pList->UpdateWindow();  
            }  
        }  

//// If we drag outside current window we need 
                //   to adjust the highlights displayed
        if (pDropWnd != m_pDropWnd)
        {
                        //If we drag over the CListCtrl header, turn off the 
                        // hover highlight
            if (m_nDropIndex != -1) 
            {
                TRACE("m_nDropIndex is -1/n");
                CListCtrl* pList = (CListCtrl*)m_pDropWnd;
                VERIFY (pList->SetItemState (m_nDropIndex, 0, 
                                                             LVIS_DROPHILITED));
                // redraw item
                VERIFY (pList->RedrawItems (m_nDropIndex, 
                                                           m_nDropIndex));
                pList->UpdateWindow ();
                m_nDropIndex = -1;
   }
            else //If we drag out of the CListCtrl altogether
            {
                TRACE("m_nDropIndex is not -1/n");
                CListCtrl* pList = (CListCtrl*)m_pDropWnd;
                int i = 0;
                int nCount = pList->GetItemCount();
                for(i = 0; i < nCount; i++)
                {
                    pList->SetItemState(i, 0, LVIS_DROPHILITED);
                }
                pList->RedrawItems(0, nCount);
                pList->UpdateWindow();
            }
        }




当我们移动鼠标的时候,我们需要保持跟踪我们拖动过什么窗口,这样当我们释放鼠标时我们知道把项目放到哪个控件上了。

所以我们把它保留到我们的成员变量。



[cpp]
view plaincopyprint?

// Save current window pointer as the CListCtrl we are dropping onto

m_pDropWnd = pDropWnd;
// Convert from screen coordinates to drop target client coordinates

pDropWnd->ScreenToClient(&pt);

[cpp] 
view plaincopyprint?

//If we are hovering over a CListCtrl we need to adjust
  
        //the highlights   
        if(pDropWnd->IsKindOf(RUNTIME_CLASS (CListCtrl)))  
        {              
            UINT uFlags;  
            CListCtrl* pList = (CListCtrl*)pDropWnd;  
            // Turn off hilight for previous drop target
  
            pList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED);  
            // Redraw previous item
  
            pList->RedrawItems (m_nDropIndex, m_nDropIndex);  
            // Get the item that is below cursor
  
            m_nDropIndex = ((CListCtrl*)pDropWnd)->HitTest(pt, &uFlags);  
            // Highlight it 
  
            pList->SetItemState(m_nDropIndex, LVIS_DROPHILITED,   
                                           LVIS_DROPHILITED);  
            // Redraw item   
            pList->RedrawItems(m_nDropIndex, m_nDropIndex);  
            pList->UpdateWindow();  
        }  
        // Lock window updates   
        m_pDragImage->DragShowNolock(true);  
    }  

//If we are hovering over a CListCtrl we need to adjust
        //the highlights
        if(pDropWnd->IsKindOf(RUNTIME_CLASS (CListCtrl)))
        {            
            UINT uFlags;
            CListCtrl* pList = (CListCtrl*)pDropWnd;
            // Turn off hilight for previous drop target
            pList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED);
            // Redraw previous item
            pList->RedrawItems (m_nDropIndex, m_nDropIndex);
            // Get the item that is below cursor
            m_nDropIndex = ((CListCtrl*)pDropWnd)->HitTest(pt, &uFlags);
            // Highlight it
            pList->SetItemState(m_nDropIndex, LVIS_DROPHILITED, 
                                           LVIS_DROPHILITED);
            // Redraw item
            pList->RedrawItems(m_nDropIndex, m_nDropIndex);
            pList->UpdateWindow();
        }
        // Lock window updates
        m_pDragImage->DragShowNolock(true);
    }






完成拖放,处理放的动作:

我们在此几乎完成了所有动作。再次使用类向导,添加一个WM_LBUTTONUP消息的处理函数。这部分很短很精致。

和上面的OnMouseMove函数一样,我们仅仅处理和拖放相关的代码

[cpp]
view plaincopyprint?

if (m_bDragging)
{

[cpp] 
view plaincopyprint?

// Release mouse capture, so that other controls 
  
                // can get control/messages
  
        ReleaseCapture ();  

// Release mouse capture, so that other controls 
                // can get control/messages
        ReleaseCapture ();




当我们释放了物件,我们不再处理拖动处理。

[cpp]
view plaincopyprint?

// Note that we are NOT in a drag operation

m_bDragging = FALSE;

[cpp] 
view plaincopyprint?

// End dragging image   
        m_pDragImage->DragLeave (GetDesktopWindow ());  
        m_pDragImage->EndDrag ();  
        delete m_pDragImage;   
        //must delete it because it was created at the beginning of the drag  

// End dragging image
        m_pDragImage->DragLeave (GetDesktopWindow ());
        m_pDragImage->EndDrag ();
        delete m_pDragImage; 
        //must delete it because it was created at the beginning of the drag




跟我们在OnMouseMove函数中处理的那样,我们找出鼠标在哪,以及所处的窗口。然后我们检测是否是一个CListCtrl窗口。

如果是,我们处理实际的放动作。为了容易阅读。我让处理复制和移动的代码打包进DropItemOnList函数中(如下所示)

[cpp]
view plaincopyprint?

CPoint pt (point); //Get current mouse coordinates

ClientToScreen (&pt); //Convert to screen coordinates

// Get the CWnd pointer of the window that is under

//the mouse cursor
CWnd* pDropWnd = WindowFromPoint (pt);
ASSERT (pDropWnd); //make sure we have a window pointer

// If window is CListCtrl, we perform the drop

if (pDropWnd->IsKindOf (RUNTIME_CLASS (CListCtrl)))
{
m_pDropList = (CListCtrl*)pDropWnd;
//Set pointer to the list we are dropping on

DropItemOnList(m_pDragList, m_pDropList);
//Call routine to perform the actual drop

}
}

[cpp] 
view plaincopyprint?

void DropItemOnList(CListCtrl* pDragList, CListCtrl* pDropList);  

void DropItemOnList(CListCtrl* pDragList, CListCtrl* pDropList);




以下是实际的函数:

[cpp]
view plaincopyprint?

void CDragTestDlg::DropItemOnList(CListCtrl* pDragList,
CListCtrl* pDropList)
{
//This routine performs the actual drop of the item dragged.

//It simply grabs the info from the Drag list (pDragList)

// and puts that info into the list dropped on (pDropList).

//Send: pDragList = pointer to CListCtrl we dragged from,

// pDropList = pointer to CListCtrl we are dropping on.

//Return: nothing.

////Variables
char szLabel[256];
LVITEM lviT;
LVITEM* plvitem;
lvItem* pItem;
lvItem lvi;
// Unhilight the drop target
pDropList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED);
//Set up the LV_ITEM for retrieving item from pDragList and adding the

//new item to the pDropList

ZeroMemory(&lviT, sizeof (LVITEM)); //allocate and clear memory space

// for LV_ITEM

lviT.iItem = m_nDragIndex;
lviT.mask = LVIF_TEXT;
lviT.pszText = szLabel;
lviT.cchTextMax = 255;
lvi.plvi = &lviT;
lvi.plvi->iItem = m_nDragIndex;
lvi.plvi->mask = LVIF_TEXT;
lvi.plvi->pszText = szLabel;
lvi.plvi->cchTextMax = 255;
if(pDragList->GetSelectedCount() == 1)
{
// Get item that was dragged

pDragList->GetItem (lvi.plvi);
lvi.sCol2 = pDragList->GetItemText(lvi.plvi->iItem, 1);
// Delete the original item (for Move operation)

// This is optional. If you want to implement a Copy

// operation, don't delete. This works very well though

// for re-arranging items within a CListCtrl. It is written

// at present such that when dragging from one list to the

// other the item is copied, but if dragging within one list,

// the item is moved.

if(pDragList == pDropList)
{
pDragList->DeleteItem (m_nDragIndex);
if(m_nDragIndex < m_nDropIndex) m_nDropIndex--;
//decrement drop index to account for item

//being deleted above it

}
// Insert item into pDropList

// if m_nDropIndex == -1, iItem = GetItemCount()

// (inserts at end of list), else iItem = m_nDropIndex

lvi.plvi->iItem = (m_nDropIndex == -1) ?
pDropList->GetItemCount () : m_nDropIndex;
pDropList->InsertItem (lvi.plvi);
pDropList->SetItemText(lvi.plvi->iItem, 1, (LPCTSTR)lvi.sCol2);
// Select the new item we just inserted

pDropList->SetItemState (lvi.plvi->iItem, LVIS_SELECTED,
LVIS_SELECTED);
}
else //more than 1 item is being dropped

{
//We have to parse through all of the selected items from the

// DragList
//1) Retrieve the info for the items and store them in memory

//2) If we are reordering, delete the items from the list

//3) Insert the items into the list (either same list or

// different list)

CList<lvItem*, lvItem*> listItems;
POSITION listPos;
//Retrieve the selected items

POSITION pos = pDragList->GetFirstSelectedItemPosition();
//iterator for the CListCtrl

while(pos) //so long as we have a valid POSITION, we keep

// iterating

{
plvitem = new LVITEM;
ZeroMemory(plvitem, sizeof(LVITEM));
pItem = new lvItem;
//ZeroMemory(pItem, sizeof(lvItem));

//If you use ZeroMemory on the lvItem struct,

//it creates an error when you try to set sCol2

pItem->plvi = plvitem;
pItem->plvi->iItem = m_nDragIndex;
pItem->plvi->mask = LVIF_TEXT;
pItem->plvi->pszText = new char;
//since this is a pointer to the string, we need a

//new pointer to a new string on the heap

pItem->plvi->cchTextMax = 255;
m_nDragIndex = pDragList->GetNextSelectedItem(pos);
//Get the item

pItem->plvi->iItem = m_nDragIndex; //set the index in

//the drag list to the selected item

pDragList->GetItem(pItem->plvi); //retrieve the

// information

pItem->sCol2 = pDragList->GetItemText(
pItem->plvi->iItem, 1);
//Save the pointer to the new item in our CList

listItems.AddTail(pItem);
} //EO while(pos) -- at this point we have deleted the moving

// items and stored them in memory

if(pDragList == pDropList) //we are reordering the list (moving)

{
//Delete the selected items

pos = pDragList->GetFirstSelectedItemPosition();
while(pos)
{
pos = pDragList->GetFirstSelectedItemPosition();
m_nDragIndex = pDragList->GetNextSelectedItem(pos);
pDragList->DeleteItem(m_nDragIndex);
//since we are MOVING, delete the item

if(m_nDragIndex < m_nDropIndex) m_nDropIndex--;
//must decrement the drop index to account

//for the deleted items

} //EO while(pos)

} //EO if(pDragList...
//Iterate through the items stored in memory and add them

//back into the CListCtrl at the drop index

listPos = listItems.GetHeadPosition();
while(listPos)
{
pItem = listItems.GetNext(listPos);
m_nDropIndex = (m_nDropIndex == -1) ?
pDropList->GetItemCount() : m_nDropIndex;
pItem->plvi->iItem = m_nDropIndex;
pDropList->InsertItem(pItem->plvi); //add the item

pDropList->SetItemText(pItem->plvi->iItem, 1,
pItem->sCol2);
pDropList->SetItemState(pItem->plvi->iItem,
LVIS_SELECTED, LVIS_SELECTED);
//highlight/select the item we just added

m_nDropIndex++;
//increment the index we are dropping at to keep the

//dropped items in the same order they were in in the

//Drag List. If we dont' increment this, the items are

//added in reverse order

//Lastly, we need to clean up by deleting our "new"

//variables

delete pItem;
} //EO while(listPos)
}
}

void CDragTestDlg::DropItemOnList(CListCtrl* pDragList,
CListCtrl* pDropList)
{
//This routine performs the actual drop of the item dragged.
//It simply grabs the info from the Drag list (pDragList)
// and puts that info into the list dropped on (pDropList).
//Send: pDragList = pointer to CListCtrl we dragged from,
// pDropList = pointer to CListCtrl we are dropping on.
//Return: nothing.
////Variables
char szLabel[256];
LVITEM lviT;
LVITEM* plvitem;
lvItem* pItem;
lvItem lvi;
// Unhilight the drop target
pDropList->SetItemState (m_nDropIndex, 0, LVIS_DROPHILITED);
//Set up the LV_ITEM for retrieving item from pDragList and adding the
//new item to the pDropList
ZeroMemory(&lviT, sizeof (LVITEM)); //allocate and clear memory space
// for LV_ITEM
lviT.iItem = m_nDragIndex;
lviT.mask = LVIF_TEXT;
lviT.pszText = szLabel;
lviT.cchTextMax = 255;
lvi.plvi = &lviT;
lvi.plvi->iItem = m_nDragIndex;
lvi.plvi->mask = LVIF_TEXT;
lvi.plvi->pszText = szLabel;
lvi.plvi->cchTextMax = 255;
if(pDragList->GetSelectedCount() == 1)
{
// Get item that was dragged
pDragList->GetItem (lvi.plvi);
lvi.sCol2 = pDragList->GetItemText(lvi.plvi->iItem, 1);
// Delete the original item (for Move operation)
// This is optional. If you want to implement a Copy
// operation, don't delete. This works very well though
// for re-arranging items within a CListCtrl. It is written
// at present such that when dragging from one list to the
// other the item is copied, but if dragging within one list,
// the item is moved.
if(pDragList == pDropList)
{
pDragList->DeleteItem (m_nDragIndex);
if(m_nDragIndex < m_nDropIndex) m_nDropIndex--;
//decrement drop index to account for item
//being deleted above it
}
// Insert item into pDropList
// if m_nDropIndex == -1, iItem = GetItemCount()
// (inserts at end of list), else iItem = m_nDropIndex
lvi.plvi->iItem = (m_nDropIndex == -1) ?
pDropList->GetItemCount () : m_nDropIndex;
pDropList->InsertItem (lvi.plvi);
pDropList->SetItemText(lvi.plvi->iItem, 1, (LPCTSTR)lvi.sCol2);
// Select the new item we just inserted
pDropList->SetItemState (lvi.plvi->iItem, LVIS_SELECTED,
LVIS_SELECTED);
}
else //more than 1 item is being dropped
{
//We have to parse through all of the selected items from the
// DragList
//1) Retrieve the info for the items and store them in memory
//2) If we are reordering, delete the items from the list
//3) Insert the items into the list (either same list or
// different list)
CList<lvItem*, lvItem*> listItems;
POSITION listPos;
//Retrieve the selected items
POSITION pos = pDragList->GetFirstSelectedItemPosition();
//iterator for the CListCtrl
while(pos) //so long as we have a valid POSITION, we keep
// iterating
{
plvitem = new LVITEM;
ZeroMemory(plvitem, sizeof(LVITEM));
pItem = new lvItem;
//ZeroMemory(pItem, sizeof(lvItem));
//If you use ZeroMemory on the lvItem struct,
//it creates an error when you try to set sCol2
pItem->plvi = plvitem;
pItem->plvi->iItem = m_nDragIndex;
pItem->plvi->mask = LVIF_TEXT;
pItem->plvi->pszText = new char;
//since this is a pointer to the string, we need a
//new pointer to a new string on the heap
pItem->plvi->cchTextMax = 255;
m_nDragIndex = pDragList->GetNextSelectedItem(pos);
//Get the item
pItem->plvi->iItem = m_nDragIndex; //set the index in
//the drag list to the selected item
pDragList->GetItem(pItem->plvi); //retrieve the
// information
pItem->sCol2 = pDragList->GetItemText(
pItem->plvi->iItem, 1);
//Save the pointer to the new item in our CList
listItems.AddTail(pItem);
} //EO while(pos) -- at this point we have deleted the moving
// items and stored them in memory
if(pDragList == pDropList) //we are reordering the list (moving)
{
//Delete the selected items
pos = pDragList->GetFirstSelectedItemPosition();
while(pos)
{
pos = pDragList->GetFirstSelectedItemPosition();
m_nDragIndex = pDragList->GetNextSelectedItem(pos);
pDragList->DeleteItem(m_nDragIndex);
//since we are MOVING, delete the item
if(m_nDragIndex < m_nDropIndex) m_nDropIndex--;
//must decrement the drop index to account
//for the deleted items
} //EO while(pos)
} //EO if(pDragList...
//Iterate through the items stored in memory and add them
//back into the CListCtrl at the drop index
listPos = listItems.GetHeadPosition();
while(listPos)
{
pItem = listItems.GetNext(listPos);
m_nDropIndex = (m_nDropIndex == -1) ?
pDropList->GetItemCount() : m_nDropIndex;
pItem->plvi->iItem = m_nDropIndex;
pDropList->InsertItem(pItem->plvi); //add the item
pDropList->SetItemText(pItem->plvi->iItem, 1,
pItem->sCol2);
pDropList->SetItemState(pItem->plvi->iItem,
LVIS_SELECTED, LVIS_SELECTED);
//highlight/select the item we just added
m_nDropIndex++;
//increment the index we are dropping at to keep the
//dropped items in the same order they were in in the
//Drag List. If we dont' increment this, the items are
//added in reverse order
//Lastly, we need to clean up by deleting our "new"
//variables
delete pItem;
} //EO while(listPos)
}
}



我们简单的设置LVITEM结构同时用来获取拖放来源控件的信息,以及添加该信息进拖放目标控件。

如果你的CListCtrl控件包含图标,不要忘记改变"lvi.mask=LVIF_TEXT"所在行。



所以我们设置来LVITEM结构,然后使用GetItem(&lvi)来获取我们拖动的列表项目的信息。

但你将注意到这个不会获取第二列的信息。那时我们为什么需要lvItem结构,我们使用pItem->sCol2=pDragList->GetItemText(pItem->plvi->iItem, 1);

来获取那个信息。



当我们处理拖动多项选择时,我们在lvItem对象设置一个CList,我们处理拖动来源CListCtrl并获取所有选项信息。然后如果我们处理的是Move操作,

我们删除所有来源的选项,然后通过处理CList并添加每一个项目到CListCtrl。



正如我的样例程序所实现,我检测用户是否拖动项目到其他的CListCtrl还是在同一个CListCtrl。如果用户释放一个项目到其他的CListCtrl,然后我们会

复制项目到其它控件,如果,用户仅仅拖放到同一个控件的不同点,我们将移动项目到新的索引(这是如何实现用户给一个列表按拖动来排序)。一般来说,

如果用户移动同一个控件的项目,我们会在添加回原列表前删除原来项目(获取完项目的信息后)。我们必须先删除,因为如果我们先添加的话,索引将不一致。

并且在很多实例中我们不允许将信息写到已存在的项目中。试着思考我所说的意思。在我们添加信息回列表后删除该项目,拖动列表的项目并看看发生了什么。

(译者注:最后一句我也不知道说的啥,只能猜测,所以把原文抄上: Try it to see what I mean. Move the part where we delete the item to AFTER we have added the item to the list. Drag items around in the list and see what happens.)



最后,我们添加项目到CListCtrl并设置该项目为高亮。



很简单,不是吗?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: