I did it in a "DomainEditor" class for this huge application I wrote. All my type (domain) tables in the database could be edited by the admins of the program and since the clients called some of the types by different names than others did, I made a dialog that allowed you to edit them. Well, I didn't want to make an editor for the 15+ domain types, so I wrote a super-class that I could cast each class to, and using pointers I could make simple calls to each domain table. Each one supported all the same properties, a Description (name), an ID, an Inactive flag, and a Required flag. So, the code started with a Macro to setup my calls:
#define DomainList(Class, Description, First, Next, Item, UpdateItem, DeleteItem, IsItemRequired, MaxLength) { \
CWFLHandler *handler = new CWFLHandler; \
handler->pWFL = new Class;\
handler->LoadFirstType = (LoadFirst)&Class::First;\
handler->LoadNextType = (LoadNext)&Class::Next;\
handler->LoadType = (Load)&Class::Item;\
handler->UpdateType = (Update)&Class::UpdateItem;\
handler->DeleteType = (Delete)&Class::DeleteItem;\
handler->IsRequiredType= (IsRequired)&Class::IsItemRequired; \
handler->MAX_LENGTH = MaxLength;\
PopulateListBox(m_Domain, Description, (long)handler); }\
Then, lots of calls to the Macro: (Here is just a single one)
DomainList(CConfigWFL, "Application Parameter Types", LoadFirstParameterType, LoadNextParameterType, LoadParameterTypeByTypeId, UpdateParameterType, DeleteParameterType, IsParameterTypeRequired, LEN_APPL_PARAMETER_DESC);
Then, the calls to edit the data were all common, and I didn't have to duplicate any code at all...
For example, to populate the list with the selected item in the DropDownList (populated by the Macro), the code would look like this:
if((pWFLPtr->pWFL->*pWFLPtr->LoadFirstType)(true))
{
do
{
m_Grid.AddGridRow();
m_Grid.SetCheck(COLUMN_SYSTEM, (pWFLPtr->pWFL->*pWFLPtr->IsRequiredType)(pWFLPtr->pWFL->TypeId));
m_Grid.SetCheck(COLUMN_STATUS, pWFLPtr->pWFL->InactiveIndc == false);
m_Grid.AddTextToGrid(COLUMN_NAME, pWFLPtr->pWFL->TypeDesc);
m_Grid.AddTextToGrid(COLUMN_DEBUG, pWFLPtr->pWFL->TypeId);
m_Grid.AddTextToGrid(COLUMN_ID, pWFLPtr->pWFL->TypeId);
}
while((pWFLPtr->pWFL->*pWFLPtr->LoadNextType)());
Of, course, this was all stored in a class that was part of the dialog. And I simply created new instances of the class, stored them in the ListBox's ItemData member. So, I did have to clean all that up when the dialog closed.. I left that code out of this message however.
The class to store all this stuff in was defined as:
typedef bool (CMyWFL::*LoadFirst)(bool);
typedef bool (CMyWFL::*LoadNext)();
typedef bool (CMyWFL::*Load)(long);
typedef bool (CMyWFL::*Update)(long, const char*, bool);
typedef bool (CMyWFL::*Delete)(long);
typedef bool (CMyWFL::*IsRequired)(long);
class CWFLHandler {
public:
CWFLHandler() {};
~CWFLHandler() { if(pWFL) delete pWFL; }
CMyWFL *pWFL;
LoadFirst LoadFirstType;
LoadNext LoadNextType;
Load LoadType;
Update UpdateType;
Delete DeleteType;
IsRequired IsRequiredType;
int MAX_LENGTH;
};
CWFLHandler *pWFLPtr;
All this work made it really nice to be able to add new domains to the application with very little work to add them to the domain editor... There may have been a better way, I don't know. But this is the way I went, and it worked VERY well for me, and IMHO, it was very creative... :)