Objective Grid : PART I User’s Guide : Chapter 6 Reducing the Size of Your Application : The Control Factory Class
The Control Factory Class
Objective Grid provides an abstract base class for Control Factory Classes, the CGXAbstractControlFactory class. This class defines the interface for the Control Factory Class. In order to create a Control Factory Class, derive from CGXAbstractControlFactory and override all pure virtual methods. While the Control Factory dialog of the Build Wizard fully automates the creation of the Control Factory Class, it is helpful to know how the Control Factory Class works:
Registration of cell types and instantiation of cell type objects on demand.
Registration of “concrete implementations” for various grid features like Undo/Redo, Serialization and more. The term “concrete implementation” means that a C++ object gets allocated that is derived from an abstract C++ base class.
Registration of window classes for custom controls in dialog templates.
Registration of Cell Types
In Objective Grid each cell type is implemented through a class derived from CGXControl. CGXControl defines the necessary interface for the grid to be able to interact with cells. CGXControl also implements some default behavior for most functions. Objective Grid has no dependencies on any cell type object. You can derive custom cell type objects from CGXControl or use the default cell types. Only cell types that get registered will be linked into your application or DLL.
Registration of cell types is implemented through the following methods:
virtual CGXControl*
CreateControl(UINT nID, CGXGridCore* pGrid);
Each grid maintains a map of cell type (CGXControl) objects. A cell type is identified through the cell type id, an unsigned integer constant. Whenever a cell type is requested that is not yet registered in the grid, the grid calls CreateControl(). CreateControl() is responsible for instantiating the correct cell type object. The grid stores the cell type object in its map and will keep this cell type object alive until the grid gets out of scope. When the grid is destructed all cell type objects in the map will be destroyed.
virtual void
RegisterAllControls(CGXStylesMap* pStylesMap);
Registers the cell type names with the styles-map. This is necessary when you want the various cell types to appear in the Controls-page of the CGXStyleSheet.
virtual void
RegisterAllUserAttributes(CGXStylesMap* pStylesMap);
Registers user attribute names with the styles-map. This is necessary when you want the user attributes to appear in the User Attribute-page of the CGXStyleSheet.
Registration of Concrete Implementations for Grid Features
In Objective Grid features that are not essential for every grid application are implemented through abstract base classes. Find and Replace is an example of a feature that only gets linked into your application or DLL if a concrete implementation is registered with the grid. Objective Grid interacts with a concrete FindReplace object through an interface that is defined by an abstract base class. Whenever Objective Grid needs to call a FindReplace-specific method it first checks if a FindReplace object is available.
 
BOOL CGXGridCore::FindText(BOOL bSetCell)
{
if (m_pFindReplaceImp)
return m_pFindReplaceImp->FindText(this, bSetCell);
return FALSE;
}
In the above example m_pFindReplaceImp is a pointer to the abstract base class CGXAbstractGridFindReplaceImp. The FindReplace functionality is implemented in the CGXGridFindReplaceImp class that is derived from CGXAbstractGridFindReplaceImp. A concrete object is instantiated through the ImplementFindReplace method:
 
void CGXGridCore::ImplementFindReplace()
{
if (m_pFindReplaceImp == NULL)
AutoDeletePtr(m_pFindReplaceImp = new CGXGridFindReplaceImp);
}
Using an abstract base class eliminates any dependencies within Objective Grid to the concrete FindReplace implementation. The abstract base has no implementation and therefore no code for FindReplace needs to be linked into the application or DLL if ImplementFindReplace is not called.
Registration of concrete implementations for grid features (by calling ImplementFindReplace for example) is done with the following methods:
virtual void
InitializeGridComponents(CGXGridCore* pGrid);
This method is called from each grid at initialization time (from OnGridInitialUpdate() to be more concrete). It instantiates concrete implementations for grid features and attaches the instantiated object to the grid. The grid will keep the object alive until the grid gets out of scope. When the grid is destructed all grid feature objects will be destroyed. This method instantiates objects that are used by particular grids (referred to by pGrid).
virtual void
InitializeApplicationComponents();
This method is called from Objective Grid at application initialization time (from GXInit). It instantiates concrete implementations for various features. Objective Grid will keep the objects alive until the application terminates or GXForceTerminate() is called. Objective Grid will then destroy the objects. This method instantiates objects that are useful to the application.
NOTE >> Previous versions of Objective Grid supported the function GXTerminate(), but this function is now obsolete. Please use GXForceTerminate() as stated above.
Registration of Window Classes
Registration of window classes is implemented through the following methods:
virtual void
RegisterWndClasses(HINSTANCE hInstance);
Registers custom window classes. If, for example, CGXGridWnd gets registered, you can use the CGXGridWnd class as user control in dialog templates in your application.
virtual void
UnregisterWndClasses(HINSTANCE hInstance);
Undoes the registration of previously registered window classes.
The following code shows a sample implementation of a Control Factory Class:
 
#include "stdafx.h"
#include "gridappf.h"
 
void CControlFactory::InitializeGridComponents(CGXGridCore* pGrid)
{
pGrid->ImplementFindReplace();
pGrid->ImplementHideCells();
pGrid->ImplementAutoScroll();
}
 
void CControlFactory::InitializeApplicationComponents()
{
CGXPrintDevice::ImplementPrintDevice();
CGXStyle::ImplementCompareSubset();
CGXStyle::ImplementSerialize();
CGXStyle::ImplementSerializeOG5Compatible();
GXImplementOleDateTime();
}
 
void CControlFactory::RegisterAllControls(CGXStylesMap* pStylesMap)
{
// Basic cell types
pStylesMap->AddControl(GX_IDS_CTRL_EDIT);
pStylesMap->AddControl(GX_IDS_CTRL_HEADER);
pStylesMap->AddControl(GX_IDS_CTRL_STATIC);
}
 
CGXControl* CControlFactory::CreateControl(UINT nID,
CGXGridCore* pGrid)
{
CGXControl* pControl = NULL;
 
switch (nID)
{
case GX_IDS_CTRL_EDIT:
pControl = new CGXEditControl(pGrid, GX_IDS_CTRL_EDIT);
break;
 
case GX_IDS_CTRL_STATIC:
pControl = new CGXStatic(pGrid);
break;
 
case GX_IDS_CTRL_HEADER:
pControl = new CGXHeader(pGrid);
break;
}
 
return pControl;
}
 
void CControlFactory::RegisterAllUserAttributes(CGXStylesMap*
pStylesMap)
{
CGXControl::AddUserAttributes(pStylesMap);
}
 
void CControlFactory::RegisterWndClasses(HINSTANCE hInstance)
{
CGXGridWnd::RegisterClass(hInstance);
}
 
void CControlFactory::UnregisterWndClasses(HINSTANCE hInstance)
{
CGXGridWnd::UnregisterClass(hInstance);
}