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
CDoubleListPicker class is very straightforward. Follow the steps below to add one to an existing project.
- 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.
- 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
- 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.)
- If you want to able to tab to the control then give it the Tab stop property.
- 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
TRUE) or the right-hand list (
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
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
CStringList respectively. If
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
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.
- This function returns a reference to the title static control.
- 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 CDoubleListPicker::ID_LABEL_LEFT CDoubleListPicker::ID_LABEL_RIGHT CDoubleListPicker::ID_BTN_MOVE_RIGHT CDoubleListPicker::ID_BTN_MOVE_LEFT CDoubleListPicker::ID_BTN_MOVE_ALL_RIGHT CDoubleListPicker::ID_BTN_MOVE_ALL_LEFT CDoubleListPicker::ID_LIST_LEFT CDoubleListPicker::ID_LIST_RIGHT
Version 2.1 - 09-Jul-2003
- Updated to support Unicode.
Version 2 - 07-Feb-2003
Version 1 - 31 Jul 2002
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.
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.