Click here to Skip to main content
Click here to Skip to main content

Dynamically re-creating a list box

By , 2 Aug 2002
 

Introduction

This article is a companion article to my article Dynamically re-creating a combo box. Similarly to the combo box, I frequently find myself needing to switch a list box to or from sorted, or to or from multi select. As with the combo box, changing these styles after creation is something that a listbox does not support. The function presented here will recreate the list box so that style changes take effect. The function will retain all list items, with item data, and the currently selected items.

When the style is modified on a listbox to include or remove the LBS_SORT for example, it can be seen (by using GetStyle(), or using a tool such as Spy++) that the control does in fact have the new style, and yet the control's behaviour has not changed. The function here simply gets the current info from the control, i.e. styles, font etc, and recreates the control using these values.

How to use

I originally had a CListBox-derived class which one member function to recreate the controls, but decided that this was more trouble than it was worth, as I usually use controls derived from other bases. Therefore I have presented this as a single function, which should be included in a global library file, so that you can invoke it on any listbox at any time.

In order to change the style of a listbox, you should perform the usual method of setting the new style e.g.

list.ModifyStyle(0, LBS_SORT);

and then after than call your should call:

RecreateListBox(&list)

The function takes an optional void pointer, lpParam, which is passed to CreateEx on recreating the control. If you have special requirements when creating your controls, and you normally pass in some data for the creation parameters, then you should pass the same info in here. Most developers can simply ignore this parameter.

The Function

The function to recreate the listbox is below:

// recreate the list box by copying styles etc, and list items
// and applying them to a newly created control
BOOL RecreateListBox(CListBox* pList, LPVOID lpParam/*=NULL*/)
{
	if (pList == NULL)
		return FALSE;
	if (pList->GetSafeHwnd() == NULL)
		return FALSE;

	CWnd* pParent = pList->GetParent();
	if (pParent == NULL)
		return FALSE;

	// get current attributes
	DWORD dwStyle = pList->GetStyle();
	DWORD dwStyleEx = pList->GetExStyle();
	CRect rc;
	pList->GetWindowRect(&rc);
	pParent->ScreenToClient(&rc);	// map to client co-ords
	UINT nID = pList->GetDlgCtrlID();
	CFont* pFont = pList->GetFont();
	CWnd* pWndAfter = pList->GetNextWindow(GW_HWNDPREV);

	// create the new list box and copy the old list box items 
	// into a new listbox along with each item's data, and selection state
	CListBox listNew;
	if (! listNew.CreateEx(dwStyleEx, _T("LISTBOX"), _T(""), dwStyle, 
                                rc, pParent, nID, lpParam))
	  return FALSE;
	listNew.SetFont(pFont);
	int nNumItems = pList->GetCount();
	BOOL bMultiSel = (dwStyle & LBS_MULTIPLESEL || dwStyle & LBS_EXTENDEDSEL);
	for (int n = 0; n < nNumItems; n++)
	{
		CString sText;
		pList->GetText(n, sText);
		int nNewIndex = listNew.AddString(sText);
		listNew.SetItemData(nNewIndex, pList->GetItemData(n));
		if (bMultiSel && pList->GetSel(n))
			listNew.SetSel(nNewIndex);
	}
	if (! bMultiSel)
	{
		int nCurSel = pList->GetCurSel();
		if (nCurSel != -1)
		{
			CString sSelText;
			// get the selection in the old list
			pList->GetText(nCurSel, sSelText);
			// now find and select it in the new list
			listNew.SetCurSel(listNew.FindStringExact(-1, sSelText));
		}
	}
	// destroy the existing window, then attach the new one
	pList->DestroyWindow();
	HWND hwnd = listNew.Detach();
	pList->Attach(hwnd);

	// position correctly in z-order
	pList->SetWindowPos(pWndAfter == NULL ? &CWnd::wndBottom
                                 : pWndAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

	return TRUE;
}

See Also

History

  • Version 1 - 26 Jul 2002 - First version
  • Version 2 - 30 Jul 2002 - modified to include changes suggested by Jean-Michel LE FOL and Davide Zaccanti

License

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
Member
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.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberPony8714 Jul '10 - 19:20 
Excellent!!!
GeneralAdding Items to a listBox and get the Item IDmemberCJGun12 Sep '08 - 2:26 
Hi,
Im new to .net and what i want to do is,
Im loading the items to the lstLeft from the database!
And at the runtime i want to add the selected items to lstRight.
I was able to do that also.
But when im going to bind the Value ID of the enterd items which are now on lstRight,
It says when i set data dource,i cann't add values!!
Some one please help me on this!!!
 
this is the place I'm adding the item to the right hand side listBox(lstRight).
 
DataRowView dr = (DataRowView)lstLeft.SelectedItem;
lstRight.Items.Add(dr);
lstRight.DisplayMember = "Status";
lstRight.ValueMember = "StatusID";
 
///////////////////////////////////
And this is the place I'm Bining values to the ListBox.
 
DataRowView dr = (DataRowView)lstLeft.SelectedItem;
lstRight.Items.Add(dr);
lstRight.DisplayMember = "RefferalMechanism";
lstRight.ValueMember = "RefferalMechanismID";

.
.
.
Generalmfc listbox mouse eventsussAnonymous30 Oct '03 - 21:27 
hi; i am creating a simple mfc app with list box and edit boxes, i want to know how can i upon user mouse click on the list box item retreive that item data and display it in the edit boxes,,
what methods should i override!!!!
i can use a nutton, but i dont want that
i am fresh in mfc,, so sorry if this question is 2 trivial!!!

GeneralCreating in IE Toolbar Bandmembertools200018 Jun '03 - 17:30 
Hi
 
I have created a toolbar for IE using MS C++, which has a Dynamically created List/combo box.
 
My problem is that my control will not allow Cut and Paste via short cuts (Ctrl + C, Ctrl + V)
Does any know why this does not work? or How to get it to work?
 
Any help woule be much appriciated.
 
Thanks
Scott
GeneralProblem: Scroll bar disappearedsussGeert Delmeiren17 Dec '02 - 1:20 
Hi,
 
When I use this code for some reason after recreating the listbox with the new style (in my case: switching between single selection / multiple selection) the vertical scroll bar (in case of a lot of listbox items) that used to be there is GONE.
 
I even tried to explicitly add the style WS_EX_LEFTSCROLLBAR (I know: on the left side)
 
dwStyleEx |= WS_EX_LEFTSCROLLBAR;
before calling listNew.CreateEx() but the scroll bar doesn't appear again!
 
Any ideas?
Geert.
GeneralFYI: Solved: Scroll bar disappearedsussGeert Delmeiren17 Dec '02 - 5:08 
I found the solution.
 
For some reason (?) changing the list box from multiple select to single select must be done not by:
m_lbxServices.ModifyStyle(LBS_EXTENDEDSEL, 0);  <font color=green>// 0=Don't add any extra style</font>
RecreateListBox(&m_lbxServices);
but by
m_lbxServices.ModifyStyle(LBS_EXTENDEDSEL, WS_VSCROLL); <font color=green>// Re-add the WS_VSCROLL style</font>
RecreateListBox(&m_lbxServices);
 
i.e. The list box seems to 'lose' its WS_VSCROLL style 'somewhere'. [in RecreateListBox() ?]
Re-adding it solves the problem.
GeneralSmall correctionsussGeert Delmeiren29 Oct '02 - 1:57 
Hi Paul,
Thanks for the article. I could use it "out of the box".
 
Nevertheless I encountered a small problem when I called the function on an empty (not yet filled) multiple select mode listbox to make it a single select listbox.
 
In your code I changed
<CODE>if (! bMultiSel )</CODE>
into
<CODE>if (! bMultiSel && nNumItems)</CODE>
and the problem was gone.
Apparently GetCurSel() on an empty listbox doesn't return -1 but 0.
GeneralGood idea PaulmemberJean-Michel LE FOL26 Jul '02 - 6:58 
About your implementation, I have an idea but I ditn't test it:
As you create a temporary listbox, perhaps it is possible to detach its HWND handle and affect it to the first listbox.
With this solution, no need to re-create 2 listboxes, only one.
Good idea or not ?
GeneralRe: Good idea PaulmemberPaul S. Vickery30 Jul '02 - 3:08 
That's a very good idea! I have posted an update (version 2) which includes this and a couple of other changes.
 
---
"The way of a fool seems right to him, but a wise man listens to advice" - Proverbs 12:15 (NIV)
Generalsingle selection and multiple selection listboxesmemberNice Özgürce18 Jan '05 - 6:59 
Hello
 
I need a ListBox that will provide functionality of both single selection and multiple selection listboxes. That means I should be able to singly or multiply make selections in a listbox. I develop with Visual c++ 6.0. What would you suggest ? How would one make it ? I need not to play with colors or anything else. Any help would be greatly appreciated.
 
Nice Ozgurce

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 3 Aug 2002
Article Copyright 2002 by Paul Vickery
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid