A Dual ListBox Selection Manager
I have seen many applications that provide the user with the ability to select an item from one list and put it into another. One example is the NT User manager group memberships screen. This is commonly done by placing two listboxes side by side. Then buttons are generally used to add, add all, remove, remove all and to move items up and down in the list of choosen items. Here's a screen shot from my demo application:
I created a class named CDualListManager that handles all of the drudgery of moving items between the two lists. One list represents the list of available items and the other represents the list of choosen items (I use the word choosen instead of selected to avoid any confusion with the hilighted item in a list). This class is intended to be a member of CDialog, CFormView or CPropertyPage. All the parent class has to do is properly initialize this class and call a couple of member functions and this class will take care of the following things:
- If the "Add" button is pressed the selected item(s) are moved from the available list to the choosen list.
- If the "Add All" button is pressed all of the items in are moved from the available list to the choosen list.
- If the "Remove" button is pressed the selected item(s) are moved from the choosen list to the available list.
- If the "Remove All" button is pressed all of the items in are moved from the choosen list to the available list.
- If the "Move Up" button is pressed the selected item(s) in the choosen list are moved up in the list by one. This button can be pressed repeatedly until all of the selected items have reached the top of the list. When that occurs the button is disabled.
- If the "Move Down" button is pressed the selected item(s) in the choosen list are moved down in the list by one.
- Allows double clicking on an item to move it to the opposite list.
- When item(s) are moved from one list to another the item that was moved is selected in the list it was moved to. The list that had the item removed selects the item that is at the location of the first item that was moved. If the item at the bottom of the list is moved the item immediately above it is selected. If the last item in the list is removed there is no selection.
- Enabling/disabling of buttons - when items are moved between lists and up and down in the choosen list the availability of buttons changes. For instance if an item is moved to the top of the choosen list the "Move Up" button doesn't make sense. When this occurs the "Move Up" button is automatically disabled.
- Keyboard support - disabling a button that has the focus causes problems for keyboard users. This code checks to see if a button has the focus before it disables it. If it does the focus is forwarded to the next avaiabled control.
How to use this class:
- Add a member variable of this class type to the dialog box, property page or form view where you want to use it.
- From the initialization method (OnInitDialog() for a dialog box and a property page and OnInitialUpdate() for a view) do the following things in this order:
- Add the items to the available and choosen lists with the calls AddItemToAvailableList(...) and AddItemToChoosenList(...). The first parameter is the name of the item and the second parameter is a unique identifier for the item.
- Call InitializeControls(...) with a pointer the parent window and the IDs of all of the controls.
- Override OnCmdMsg(...)
- If you don't need certain features (like the ability to move an item up or down in the choosen list) simply provide a NULL value for that id. The rest of the class will continue work correctly. The IDs for the two lists are required since a dual list manager doesn't make sense unless it has two lists to work with.
- This code will work with single, multiple and extended listboxes.
- The order of the controls doesn't matter. You can put the choosen list on the left, right, top or bottom of the selected list. Just make sure you supply the control IDs in the right order.
The demo application uses this dual list manager in a form view, a dialog box and a property page. This code will show how to use it in a form view.
Make the following changes to OnInitialUpdate
... // Normal processing
// ADDED TO DEFAULT THE LISTS.
// This code will need to be replaced with your
// application specific code that knows what belongs
// in each list.
// ADDED TO INITIALIZE THE MANAGER CLASS
Override the OnCmdMsg method and add a call to the ProcessCmdMsg on the Dual List Manager Object.
BOOL CDualListDemoView::OnCmdMsg(UINT nID, int nCode,
void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
// ADDED TO INTERCEPT MESSAGE THAT THE DUAL
// LIST MANAGER NEEDS
// NOW CALL THE BASE CLASS
return CFormView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
Add the following member to your header file.