| | | | Browse by category |
Problem
I can't get more than 32 items to work correctly in CGXCheckListComboBox. Is this because of the fact that it uses a bitmapped integer (32 bit long) to pass the choices around? How can I get around this?
Cause
Action
There are many alternatives when you subclass CGXCheckListComboBox. Here are two solutions we found very convenient:
- Subclass CGXCheckListComboBox and store the checked state in a hash table that you attach to the style object through SetItemDataPtr().
- Subclass CGXCheckListComboBox and store each choice list entry separated by a comma as value in the cell.
Solution a: Subclass CGXCheckListComboBox and store the checked state in a hash table that you attach to the style object through SetItemDataPtr().
//.h file
//CMyCheckListComboBox control |
||||
DECLARE_CONTROL(CMyCheckListComboBox) | ||||
public: | ||||
CMyCheckListComboBox(CGXGridCore* pGrid, UINT nEditID = 0, UINT nListBoxID = 0);
// Overridden these methods |
||||
};
//.cpp file #include <afxtempl.h> //include this for CMap template defenition IMPLEMENT_CONTROL(CMyCheckListComboBox,CGXCheckListComboBox) CMyCheckListComboBox::CMyCheckListComboBox(CGXGridCore* pGrid, UINT nEditID, UINT nListBoxID) |
||||
: CGXCheckListComboBox(pGrid, nEditID, nListBoxID) | ||||
{
} void CmyCheckListComboBox::OnStoreDroppedList(CListBox* lbox) |
||||
CGXStyle style = Grid()->LookupStyleRowCol(m_nRow, m_nCol); CGXCheckListComboLBox* checklbox = (CGXCheckListComboLBox*) lbox; ASSERT(checklbox->IsKindOf(RUNTIME_CLASS(CGXCheckListComboLBox))); //This is the CMap template that you should attach to if(myMap == NULL) |
||||
myMap = new CMap<int, int, BOOL, BOOL>; | ||||
// Save the selection // enable choices //Clean up the existing map before you store the new value into it myMap->RemoveAll(); for (int n = 0; n < m_nCount; n++) { |
||||
if (checklbox->GetCheck(n) == 1) { |
||||
myMap->SetAt(n,TRUE); | ||||
} | ||||
}
style.SetItemDataPtr(myMap); |
||||
}
void CMyCheckListComboBox::OnFillDroppedList(CListBox* lbox) |
||||
const CGXStyle& style = Grid()->LookupStyleRowCol(m_nRow, m_nCol); CGXCheckListComboLBox* checklbox = (CGXCheckListComboLBox*) lbox; ASSERT(checklbox->IsKindOf(RUNTIME_CLASS(CGXCheckListComboLBox))); CMap<int,int, BOOL,BOOL> *myMap; //You should have attached a CMap template of |
||||
CString s = style.GetChoiceListRef(); CString sItem; // skip first entry in choice list because while (!s.IsEmpty() && n != -1) |
||||
n = GXGetNextLine(s, sItem); lbox->AddString(sItem); m_nCount++; |
||||
} | ||||
}
// enable choices |
||||
BOOL b=FALSE;
for (int n = 0; n < m_nCount; n++) |
||||
b=FALSE; myMap->Lookup(n,b); checklbox->SetCheck(n, b); |
||||
} | ||||
} | ||||
} |
Register your control:
RegisterControl(GX_IDS_CTRL_CHECKLIST_COMBOBOX, | ||
new CMyCheckListComboBox(this, 9000,9001/*random id*/)); |
Set the control in the cell like this:
LPCTSTR szMultiChoiceList = | _T("Click Me ") _T("One ") _T("Two ") _T("Three ") _T("Four ") _T("Five ") _T("Six ") _T("Seven ") _T("Eight ") _T("Nine ") _T("Ten "); |
|||
CMap<int,int, BOOL,BOOL> *myMap = new CMap<int,int, BOOL,BOOL>; myMap->SetAt(1,TRUE); SetStyleRange(CGXRange().SetRows(nRow+1), |
||||
CGXStyle() | ||||
.SetControl(GX_IDS_CTRL_CHECKLIST_COMBOBOX) .SetChoiceList(szMultiChoiceList) .SetItemDataPtr(myMap) |
||||
); |
This will check the item "Two" (the list is 0 based).
You can retrieve the checked state of the control using:
CGXStyle style = LookupStyleRowCol(m_nRow, m_nCol); CMap<int,int, BOOL,BOOL> *myMap = style.GetItemDataPtr(); BOOL b=FALSE; if(myMap->Lookup(1,b) && b) |
||
TRACE("Item 1 is checked"); |
Solution b: Subclass CGXCheckListComboBox and store each choice list entry separated by a comma as value in the cell.
Override OnFillDroppedList( ) and OnStoreDroppedList( ) as follows:
void CMyCheckListComboBox::OnFillDroppedList(CListBox* lbox) { |
||||
const CGXStyle& style = Grid()->LookupStyleRowCol(m_nRow, m_nCol); CGXCheckListComboLBox* checklbox = (CGXCheckListComboLBox*) lbox; ASSERT(checklbox->IsKindOf(RUNTIME_CLASS(CGXCheckListComboLBox))); // fill with Choices |
||||
CString s = style.GetChoiceListRef(); CString sItem; // skip first entry in choice list because while (!s.IsEmpty() && n != -1) |
||||
n = GXGetNextLine(s, sItem); lbox->AddString(sItem); m_nCount++; |
||||
} | ||||
}
// enable choices |
||||
CString s = style.GetValueRef(); int n = 0; CString sItem; while (!s.IsEmpty() && n != -1) |
||||
n = GXGetNextLine(s, sItem); checklbox->SetCheck(_ttoi(sItem), TRUE); |
||||
} | ||||
} | ||||
}
void CMyCheckListComboBox::OnStoreDroppedList(CListBox* lbox) |
||||
CGXCheckListComboLBox* checklbox = (CGXCheckListComboLBox*) lbox; ASSERT(checklbox->IsKindOf(RUNTIME_CLASS(CGXCheckListComboLBox))); // Save the selection for (int n = 0; n < m_nCount; n++) |
||||
if (checklbox->GetCheck(n) == 1) { |
||||
wsprintf(sz, _T("%d "), n); sValue += sz; |
||||
} | ||||
}
Grid()->SetValueRange(CGXRange(m_nRow, m_nCol), sValue); |
||||
} |
Register your control:
RegisterControl(GX_IDS_CTRL_CHECKLIST_COMBOBOX, | ||
new CMyCheckListComboBox(this, 9000,9001/*random id*/)); |
Set the control in the cell like this:
SetStyleRange(CGXRange().SetRows(nRow+1), | |||
CGXStyle() | |||
.SetControl(GX_IDS_CTRL_CHECKLIST_COMBOBOX) .SetChoiceList(szMultiChoiceList) .SetValue("Two Four ") |
|||
); |
This will check the item "Two" and "Four".
You can retrieve the checked state of the by looping through the value (with GXGetNextLine( )). This will return all checked items.