65.9K
CodeProject is changing. Read more.
Home

ItemDataCombo

Jun 1, 2000

viewsIcon

92652

downloadIcon

1456

An extremely simple but useful CComboBox entension

  • Download source files - 2 Kb
  • Download demo project - 12 Kb
  • If you use CComboBox (in Drop List mode), you know it's sometimes awkward to use in situations where you need the user to pick from a set of enumerated values. You need to prevent the list box strings from being sorted and keep track of which string is in which position, or worse, do string comparisions to find out which item is selected.

    Our traditional method was to load up the list box with the strings in a fixed order - one string per enumerated value, in the same order as the enumerated values. Then we would use CComboBox::GetCurSel() to get the currently selected item; this value would tell us which string was selected.

    For example

    typedef enum eEnumeratedFruit {eApple, eOrange, eCherry};
    
    const char *pStrings[] = {"Apple", "Orange", "Cherry"};
    
    for (int i=0; i < numStrings; i++)
       m_combo.AddString(pStrings[i]);
    
    ...
    
    // find out which was selected
    eEnumeratedFruit eSelFruit = (eEnumeratedFruit)m_combo.GetCurSel();
    

    This works fine... until we want to re-order the strings without changing the order of the enumerated values. For example, if we wanted to put the fruits into the list box in alphabetical order (Apple, Cherry, Orange) this code would fail because the enum is ordered Apple, Orange, Cherry. Even worse, if we only wanted to skip items in the middle of the enumeration (ex. Apple, Cherry, not Orange)... Using CComboBox, there is simply no way to handle that situation in an elegant and generic fashion - without doing exactly what CItemDataCombo does, of course.

    So, we wrote the CItemDataCombo box.

    CItemDataCombo is a very simple class. There are only three functions:

    // a specialized AddString 
    int   AddString(const char *pString, DWORD dwData);
    
    // get the item data for the currently selected item
    DWORD GetCurSelData();
    
    // select the string that has dwData for its item data
    int   SelectItemData(DWORD dwData);
    
    For example:
    typedef enum eEnumeratedFruit {eBanana, 
                                   eApple, 
                                   eOrange, 
                                   eCherry, 
                                   eGrape, 
                                   eBlueberry};
    
    ...
    
    // add the strings, along with their associated enum value
    m_combo.AddString("Banana", (DWORD)eBanana);
    m_combo.AddString("Apple", (DWORD)eApple);
    m_combo.AddString("Orange", (DWORD)eOrange);
    m_combo.AddString("Grape", (DWORD)eGrape);
    m_combo.AddString("Blueberry", (DWORD)eBlueberry);
    m_combo.AddString("Cherry", (DWORD)eCherry);
    
    ...
    
    // select the item that corresponds to the eApple value
    m_combo.SelectItemData((DWORD)eApple);
    
    ...
    
    // which value has the user selected?
    eEnumeratedFruit eSelFruit = (eEnumeratedFruit)m_combo.GetCurSelData();	
    

    Using CItemDataCombo, you can add the strings in any order, use any subset of possible enumerated values in the box, etc..

    It has simplified CComboBox usage tremendously. No more worrying about the order of the list box strings! Plus, we can leave the "Sort" property on in the dialog editor, which sometimes makes things nice for users.

    The only annoying part of the whole thing is the need to cast to and from the enumerated value when setting, getting data. But, this could be easily solved with a templated class.