Click here to Skip to main content
13,087,797 members (82,315 online)
Click here to Skip to main content
Add your own
alternative version


37 bookmarked
Posted 30 Jul 2002

Double List Picker

, 16 Jul 2003
Rate this:
Please Sign up or sign in to vote.
Control to allow users to pick items from a list, and add to another list

DoublelistPicker Demo

DoubleListPicker Horizontal View


It is quite common in applications to see two lists, where the user can 'move' one or more items from one list to the other. For instance, one list may show a list of users in a group, while the other list shows those user not in the group. The user can then add users to the group or remove them from the group.

Whilst it's not very difficult to simply add two lists to your application, along with buttons for moving the items, this control makes it easier by wrapping up the lists and the buttons, along with labels for the lists. The control supports dynamic resizing, and allows access to the lists directly, or via its own functions

How to use it

Using the CDoubleListPicker class is very straightforward. Follow the steps below to add one to an existing project.

  1. After putting the source files (DoubleListPicker.cpp and DoubleListPicker.h) into the directory you wish to use them from, add the files to your Visual Studio project.
  2. In the resource editor, add a static control where you wish the picker to be located, and give it an id other than its default IDC_STATIC.
  3. It's a good idea to give it a Client edge or Static edge so that you can see where the edge of the control is at design-time. (These styles will be removed at run-time when sub-classing the control. Don't give it a border unless you really want a border, as this (WS_BORDER) cannot be removed at run-time.)
  4. If you want to able to tab to the control then give it the Tab stop property.
  5. In Class Wizard add a member variable for your static control, selecting "Control" from the "Category" list, and selecting "CDoubleListPicker" from the "Variable Type" list. (If CDoubleListPicker does not appear in the list, you may need to delete your class wizard file (.clw) and regenerate it).


The list controls, labels, and buttons are created by the control on creation, or on sub-classing. The 'child' controls are created as siblings of the controls rather than children as this means that tabbing, accelerators etc will still work correctly.

The picker control will manage these child controls as though it were one control, so that resizing, hiding/showing, enabling/disabling etc of the picker will move/show/hide etc the child controls accordingly.

In order to get the picker control to be able to handle the list and button notifications, these controls are sub-classed, and the notification reflected, and passed on to the picker control. After reflection they are then passed on the picker's parent, and so it is possible to act on any notifications there if required.


The public functions in the class are as follows:

Standard empty constructor

virtual BOOL Create(LPCTSTR lpszTitle, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
This is virtually identical to CStatic::Create except that it grabs the supplied window text to use as the control's title text, and adds the WS_CHILD style. It then calls CStatic::Create to do the creation.

int AddListItem(BOOL bLeft, LPCSTR lpszItem, LPVOID lpData);
int AddListItem(BOOL bLeft, LPCSTR lpszItem, DWORD dwData = 0);
These functions can be used to add an item to either the left-hand list (if bLeft is TRUE) or the right-hand list (bLeft is FALSE). In addition to specifying a string to be added to the list, you can (optionally) specify data to be attached to the list item, as a void pointer, or a DWORD respectively.

int AddListItems(BOOL bLeft, const CStringArray& saItems);
int AddListItems(BOOL bLeft, const CStringList& slistItems);
These functions allow you to add more than one item to the lists at a time, from a CStringArray or CStringList respectively. If bLeft is TRUE then the items will be added to the left-hand list, else they will be added to the right-hand list. The functions return the number of items added to the list. It is not possible to add data using these functions.

int GetListItems(BOOL bLeft, CStringArray& saItems);
int GetListItems(BOOL bLeft, CStringList& slistItems);
Similarly to the functions above, this will retrieve the items from a list into a CStringArray or CStringList respectively. Again bLeft specifies which list's items to retrieve. The functions return the number of items retrieved.

void SetListSort(BOOL bLeft, BOOL bSort = TRUE);
This function can be used to toggle whether either of the lists is sorted. It may be called before or after the control has been created.

void SetListMultiSel(BOOL bLeft, BOOL bMultiSel = TRUE);
This function can be used to toggle whether either of the lists is allows multiple (extended) selection. It may be called before or after the control has been created.

void SetTitle(LPCSTR lpszTitle = NULL);
This function sets the control's title. It may be called before or after the control has been created.

void SetLabels(LPCSTR lpszLabelLeft = NULL, LPCSTR lpszLabelRight = NULL);
This function sets either the left- or right-hand side label. It may be called before or after the control has been created.

CListBox& GetListCtrl(BOOL bLeft = TRUE);
This function returns a reference to either the left- or right-hand side list control.

CStatic& GetLabelCtrl(BOOL bLeft = TRUE);
This function returns a reference to either the left- or right-hand side label control.

CStatic& GetTitleCtrl();
This function returns a reference to the title static control.

CString GetTitle();
This function returns the current title text.

CString GetLabel(BOOL bLeft = TRUE);
This functions returns the current label text for either list.

void SetHorizontal(BOOL bHorizontal = TRUE);
Set the lists horizontally.

BOOL GetHorizontal() const;
Returns whether the lists are placed horizontally.


To allow the picker's parent to act on notification messages, the picker's controls IDs are enumerated as follows:

CDoubleListPicker::ID_TITLE               // Title static control
CDoubleListPicker::ID_LABEL_LEFT          // Left label
CDoubleListPicker::ID_LABEL_RIGHT         // Right Label
CDoubleListPicker::ID_BTN_MOVE_RIGHT      // ">" button
CDoubleListPicker::ID_BTN_MOVE_LEFT       // "<" button
CDoubleListPicker::ID_BTN_MOVE_ALL_RIGHT  // ">>" button
CDoubleListPicker::ID_BTN_MOVE_ALL_LEFT   // "<<" button
CDoubleListPicker::ID_LIST_LEFT           // Left list
CDoubleListPicker::ID_LIST_RIGHT          // Right list


Version 2.1 - 09-Jul-2003

  • Updated to support Unicode.

Version 2 - 07-Feb-2003

Version 1 - 31 Jul 2002

  • First version


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


About the Author

Paul Vickery
Software Developer (Senior)
United Kingdom United Kingdom
Originally from an electronics background, I moved into software in 1996, partly as a result of being made redundant, and partly because I was very much enjoying the small amount of coding (in-at-the-deep-end-C) that I had been doing!

I swiftly moved from C to C++, and learned MFC, and then went on to real-time C on Unix. After this I moved to the company for which I currently work, which specialises in Configuration Management software, and currently program mainly in C/C++, for Windows. I have been gradually moving their legacy C code over to use C++ (with STL, MFC, ATL, and WTL). I have pulled in other technologies (Java, C#, VB, COM, SOAP) where appropriate, especially when integrating with third-party products.

In addition to that, I have overseen the technical side of the company website (ASP, VBScript, JavaScript, HTML, CSS), and have also worked closely with colleagues working on other products (Web-based, C#, ASP.NET, SQL, etc).

For developing, I mainly use Visual Studio 2010, along with an in-house-designed editor based on Andrei Stcherbatchenko's syntax parsing classes, and various (mostly freeware) tools. For website design, I use Dreaweaver CS3.

When not developing software, I enjoy listening to and playing music, playing electric and acoustic guitars and mandolin.

You may also be interested in...

Comments and Discussions

Questionany c#/.net version available? Pin
coffeenkfc24-Nov-08 9:55
membercoffeenkfc24-Nov-08 9:55 
AnswerRe: any c#/.net version available? Pin
Paul S. Vickery6-Jan-09 0:14
memberPaul S. Vickery6-Jan-09 0:14 
GeneralRe: any c#/.net version available? Pin
coffeenkfc6-Jan-09 8:09
membercoffeenkfc6-Jan-09 8:09 
GeneralRe: any c#/.net version available? Pin
brianlj24-Jun-09 12:53
memberbrianlj24-Jun-09 12:53 
GeneralResetContent Pin
varandas7928-Mar-06 22:36
membervarandas7928-Mar-06 22:36 
AnswerRe: ResetContent Pin
Paul S. Vickery6-Jan-09 0:22
memberPaul S. Vickery6-Jan-09 0:22 
GeneralThank You, a very nice example Pin
Dieter Hammer17-Jul-03 20:30
memberDieter Hammer17-Jul-03 20:30 
GeneralTwo Comments Pin
James Curran18-Feb-03 1:03
memberJames Curran18-Feb-03 1:03 
GeneralAssigning ID's to controls Pin
Patje12-Feb-03 21:07
memberPatje12-Feb-03 21:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.170813.1 | Last Updated 17 Jul 2003
Article Copyright 2002 by Paul Vickery
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid