ChoiceListButton Control


I wanted to have a button that would display a selection of choices to the user.
I could of course use an ownerdraw dropdown box. The problem with that solution, is that, when the dropdown is collapsed it will display the last chosen item always insted of some descriptive text.
That was why i opted for a custom solution.



Optionally, the control can use the freeware library 'ITCLib' from Interface technologies, Inc. This is a great library and I will suggest that every MFC developer takes a look at it - it is a real time saver.

ITCLib has only been used for painting the small arrow on the button, and is as such not an integreated part of the control. That is why all references to ITCLib is initially disabled via preprocessor statements, so the sample should compile fine on installations without the library.

To enable ITCLib:

  • If you have ITCLib installed and you want to enable it, do the following:
  • In Project Settings - C/C++ - Preprocessor - Preprocessor definitions, add _ITCDLL
  • In Project Settings - C/C++ - Preprocessor - Additional include directories, add the folder with your ITCLib header files
  • In Project Settings - Link - Input - Additional Library Path, add the folder with your ITCLib lib-files

That's it!

If you want to use you own button class for painting the arrow or what ever it is you want to paint on the button surface, you could enherit CChoiceWindowBtn from your own class instead of CButton or ITCImageButton.


Using the control

To use the control, create a project and add these files:

drop_arrow.bmp (or another bitmap)

Assign the bitmap the resource name "DROP_ARROW" - notice as  a string - not as an integer ID.

Next add a button to a dialog and use the member functions from you WM_INITDIALOG handler.

Add an object of type CChoiceWindowBtn to the dialog class. Make sure to add the header include too.

Example - notice the use of preprocessor definitions.

// TODO: Add extra initialization here

#ifdef _ITCDLL	 	
	m_btnDropDown.SubclassControl(IDC_OPTIONS, this);
	m_btnDropDown.AddImage("DROP_ARROW", -1, RGB(255,0,255));
	m_btnDropDown.SubclassDlgItem(IDC_OPTIONS, this);

	m_btnDropDown.AddChoice("Name", TRUE);
	m_btnDropDown.AddChoice("Address", TRUE);
	m_btnDropDown.AddChoice("Notes", FALSE);
	m_btnDropDown.AddChoice("Telephone", TRUE);



The control is accessed through the class CChoiceWindowButton. It has a few simple member functions:



void AddChoice(LPCTSTR szText, BOOL bChecked=FALSE)

Return value
szText: The text to display as a choice.
bChecked: Should the choice be iniitally checked or not.
Adds a new choice to the list.



void Reset()

Return value
Deletes all the items from the choice list.


BOOL GetCheck(int iItem)

Return value
Boolean - the state of the choice specified by iItem
nItem: Zero based index of the item to query the state for.
Returns TRUE if the choice had a check mark, and FALSE if the choice was not checked by the user.



void SetCheck(int iItem, BOOL bCheck=TRUE)

Return value
iItem: Zero based index of the item to query the state for.
bCheck: Boolean value. If true, the item is checked otherwise it is unchecked.


int  GetItemCount()

Return value
The number of items in the list.



CListCtrl&  GetListCtrl()

Return value
A reference to the underlying CListCtrl object 
You access the list control like this:
CListCtrl& list = btnChoiceList.GetListCtrl();



void  RemoveAt(int iIndex)

Return value
The index of the item to remove from the list.



BOOL m_bDisableIfEmpty

Boolean value, that specifies if the button is disbaled if the choice list does not contain any items. The default value is TRUE.



vid Reset()

Return value
Removes all the items from the list.


Download demo project - 25 KB


  • Corrections for Choice Button

    Posted by Legacy on 05/14/2000 12:00am

    Originally posted by: Don Schindler

    This is a really great button! However I noticed that you cannot get the first option state, as the code is written. Looking at the code for GetChecked, the first option will always be item number zero (this uses a zero-based list). The code shown here performs an ASSERT check to make sure the item being checked has an item number larger than zero.

    BOOL CChoiceWindowBtn::GetCheck(int iItem)
    // Is the item with index iItem checked?
    ASSERT(iItem>0 && iItem<m_choiceArray.GetSize());

    CChoice* pChoice = m_choiceArray[iItem];

    return (pChoice->bChecked);

    To fix this, change the ASSERT line to read:
    ASSERT(iItem>=0 && iItem<m_choiceArray.GetSize());

    The important part is "iItem >= 0"
    This allows checking of the first item.

    - Don Schindler
    IBM / CMT

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As the mobile enterprise marketplace expands and customer needs grow more diverse, Samsung recognizes that solution partners and developers play an essential role by continually innovating to meet their customers' needs. Samsung works to provide these developers and partners with the latest tools and resources needed to create these solutions. Read this program guide to learn how the Samsung Enterprise Alliance Program provides partners and developers with Samsung enterprise software development kits (SDKs) …

  • U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there's simply not enough quality talent to go around. In response, companies often resort to inferior solutions -- hiring substandard developers and engineers, recruiting talent on a part-time or temporary basis, poaching people from competitors, or burdening an already stressed IT staff for more of their labor. Fortunately, there's a better solution. Read this white paper to learn the business value of …

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date