Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

Moving Listbox Items Up and Down

4.50/5 (5 votes)
13 Oct 2013CPOL 29.2K   461  
For single or multiple selection CListBox

Image 1

Image 2

Introduction

After some search without success about doing up / down of CListbox items (with multiple selection), here is my solution.

The code below is doing roll up/down: First item goes to last position on UP; last item goes to first position on DOWN.

Using the Code

Insert the 2 files in your project:

C++
Function_1D.h and Function_1D.cpp 

Example of use:

C++
//----------------------------------------------------------------------------
void CListBoxMoveItem::OnBnClickedButton20()    //^
{
    Func_1::ListBox_UpItem( &m_cListBox );    //Up selected items
    UpdateData( FALSE );
}

//----------------------------------------------------------------------------
void CListBoxMoveItem::OnBnClickedButton21()    //v
{
    Func_1::ListBox_DownItem( &m_cListBox  );    //down selected items
    UpdateData( FALSE );
}

The code is in a separate function file Function_1D:

C++
//Function_1D.h
namespace Func_1 
{
BOOL ListBox_UpItem( CListBox* pListBox );   //Up selected items
BOOL ListBox_DownItem( CListBox* pListBox ); //down selected items
} 

//Function_1D.cpp
//-----------------------------------------------------------------------
BOOL Func_1::ListBox_UpItem( CListBox* pListBox )    //Up selected items
{
    int iPos = 0;
    int iLigne0 = -1;
    int iLigne1 = 0;
    int iLigne2 = 0;
    CString sItemsM = "";
    CString sItems1 = "";
    CString sItems2 = "";

    int nCount = pListBox->GetCount();

    int nSelCount = pListBox->GetSelCount();
    //http://msdn.microsoft.com/en-us/library/fycfcb17%28v=vs.90%29.aspx
//DEBUT Simple sélection
    if ( nSelCount == LB_ERR )
    //If the list box is a single-selection list box, the return value is LB_ERR (-1).
    {
        int iPos = pListBox->GetCurSel();

        if ( iPos != 0 )
        {
            iLigne1 = iPos - 1;
            iLigne2= iPos;

            pListBox->GetText(iLigne1, sItems1); 
            pListBox->GetText(iLigne2, sItems2);
            //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
            pListBox->InsertString(iLigne1, sItems2);
            pListBox->DeleteString(iLigne2 + 1);
            //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx
        }
        else
        {
            iLigne1 = 0;
            iLigne2= nCount - 1;

            pListBox->GetText(iLigne2, sItems2);

            //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
            pListBox->InsertString(iLigne1, sItems2);
            pListBox->DeleteString(iLigne1 + 1);
            //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx

            //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
            pListBox->InsertString(iLigne2, sItemsM);
            pListBox->DeleteString(iLigne2 + 1);
            //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx
        }
        return TRUE;
    }
//FIN Simple sélection

//DEBUT Get the indexes of all the selected items in aryListBoxSel
    CArray<int,int> aryListBoxSel;
    aryListBoxSel.SetSize(nSelCount);
    pListBox->GetSelItems(nSelCount, aryListBoxSel.GetData()); 
    AFXDUMP(aryListBoxSel);    // Dump the selection array.
//FIN  Get the indexes of all the selected items in aryListBoxSel

//DEBUT Multi-Sélection
    for(int i = 0; i < nSelCount; i++)
    {
        iPos = aryListBoxSel.GetAt(i);

        if ( iPos != 0 )
        {
            iLigne1 = iPos - 1;
            iLigne2= iPos;

            pListBox->GetText(iLigne1, sItems1); 
            pListBox->GetText(iLigne2, sItems2);
            //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
            pListBox->InsertString(iLigne1, sItems2);
            pListBox->DeleteString(iLigne2 + 1);
            //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx
            if ( iPos == (iLigne0 + 1 ) )
            {
                iLigne0++;
            }
        }
        else
        {
            iLigne0 = 0;
            pListBox->GetText(iLigne0, sItemsM);
        }
    }

    if ( iLigne0 != -1)
    {
        iLigne1 = iLigne0;
        iLigne2= nCount - 1;

        pListBox->GetText(iLigne2, sItems2);

        //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
        pListBox->InsertString(iLigne1, sItems2);
        pListBox->DeleteString(iLigne1 + 1);
        //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx

        //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
        pListBox->InsertString(iLigne2, sItemsM);
        pListBox->DeleteString(iLigne2 + 1);
        //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx
    }
//FIN Multi-Sélection

//DEBUT Re-Sélection des items
    for(int i = 0; i < nCount; i++)
    {
        pListBox->SetSel( i, FALSE);
    }
    for(int i = 0; i < nSelCount; i++)
    {
        iPos = aryListBoxSel.GetAt(i);
        if ( iPos != 0 )
        {
            pListBox->SetSel( iPos -1, TRUE);
        }
        else
        {
            pListBox->SetSel( nCount-1, TRUE);
        }
    }
//FIN Re-Sélection des items
    return TRUE;
}

//-----------------------------------------------------------------------
BOOL Func_1::ListBox_DownItem( CListBox* pListBox  )    //down selected items
{
    int iPos = 0;
    int iLigne0 = -1;
    int iLigne1 = 0;
    int iLigne2 = 0;
    CString sItemsM = "";
    CString sItems1 = "";
    CString sItems2 = "";

    int nCount = pListBox->GetCount();

    int nSelCount = pListBox->GetSelCount();
    //http://msdn.microsoft.com/en-us/library/fycfcb17%28v=vs.90%29.aspx
//DEBUT Simple sélection
    if ( nSelCount == LB_ERR )
    //If the list box is a single-selection list box, the return value is LB_ERR (-1).
    {
        int iPos = pListBox->GetCurSel();

        if ( iPos != (nCount - 1) )
        {
            iLigne1 = iPos;
            iLigne2= iPos + 1;

            pListBox->GetText(iLigne1, sItems1); 
            pListBox->GetText(iLigne2, sItems2);
            //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
            pListBox->InsertString(iLigne1, sItems2);
            pListBox->DeleteString(iLigne2 + 1);
            //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx
        }
        else
        {
            iLigne1 = 0;
            iLigne2= nCount - 1;

            pListBox->GetText(iLigne2, sItems2);

            //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
            pListBox->InsertString(iLigne1, sItems2);
            pListBox->DeleteString(iLigne1 + 1);
            //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx

            //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
            pListBox->InsertString(iLigne2, sItemsM);
            pListBox->DeleteString(iLigne2 + 1);
            //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx
        }
        return TRUE;
    }
//FIN Simple sélection

//DEBUT Get the indexes of all the selected items in aryListBoxSel
    CArray<int,int> aryListBoxSel;
    aryListBoxSel.SetSize(nSelCount);
    pListBox->GetSelItems(nSelCount, aryListBoxSel.GetData()); 
    AFXDUMP(aryListBoxSel);    // Dump the selection array.
//FIN  Get the indexes of all the selected items in aryListBoxSel

//DEBUT Multi-Sélection
    for(int i = (nSelCount-1); i >=0; i--)
    {
        iPos = aryListBoxSel.GetAt(i);

        if ( iPos != (nCount - 1) )
        {
            iLigne1 = iPos;
            iLigne2= iPos + 1;

            pListBox->GetText(iLigne1, sItems1); 
            pListBox->GetText(iLigne2, sItems2);
            //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
            pListBox->InsertString(iLigne1, sItems2);
            //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx
            pListBox->DeleteString(iLigne2 + 1);
            if ( iPos == (iLigne0 - 1) )
            {
                iLigne0--;
            }
        }
        else
        {
            iLigne0 = nCount - 1;
            pListBox->GetText(iLigne0, sItemsM);
        }
    }

    if ( iLigne0 != -1)
    {
        iLigne1 = iLigne0;
        iLigne2 = 0;

        pListBox->GetText(iLigne2, sItems2);

        //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
        pListBox->InsertString(iLigne1, sItems2);
        pListBox->DeleteString(iLigne1 + 1);
        //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx

        //InsertString: http://msdn.microsoft.com/en-us/library/80ay18e5%28v=vs.90%29.aspx
        pListBox->InsertString(iLigne2, sItemsM);
        pListBox->DeleteString(iLigne2 + 1);
        //DeleteString: http://msdn.microsoft.com/en-us/library/466e49kb%28v=vs.90%29.aspx
    }
//FIN Multi-Sélection

//DEBUT Re-Sélection des items
    for(int i = 0; i < nCount; i++)
    {
        pListBox->SetSel( i, FALSE);
    }
    for(int i = (nSelCount-1); i >=0; i--)
    {
        iPos = aryListBoxSel.GetAt(i);
        if ( iPos != (nCount - 1) )
        {
            pListBox->SetSel( iPos + 1, TRUE);
        }
        else
        {
            pListBox->SetSel( 0, TRUE);
        }
    }
//FIN Re-Sélection des items
    return TRUE;
}

//

Demo

The demo shows an example to select items from 1 Listbox to a 2nd one. The up / down enables to sort items on the 2nd Listbox.

The demo includes a modified version of WndResizer from Mizan Rahman's http://www.codeproject.com/KB/dialog/WndResizer.aspx (The original can be used, modification is for hiding/showing controls.)

Points of Interest

Remark: I tested multiple selection parts but not the single selection part.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)