t e m p o r a l 
 d o o r w a y 

Handling Uneven Form Inheritance

 

Introduction

Imagine a form and some data modules. Some of the data modules have lookup fields into each other. The form uses the data sources of the data modules.

Now imagine that you need to specialize one of the data modules. You create a new project based on the original project, and you add a data module derived from a data module in the base project.

There's just one problem here. All of the other data module and form references to components in the base class data module disappear. The base class data module global variable isn't initialized.

What Causes The Problem

When the streaming system streams in the project forms, it knows that some "global" components, like data modules and forms, may reference components within each other. So at the end of the streaming process, all of the intercomponent references at the global level undergo a fixup process. The fixup process is based on calls to Forms::FindGlobalComponent for each reference. The problem is that only the actual forms created with new or CreateForm, not their ancestors, are in Screen->DataModules and Screen->Forms, which the default FindGlobalComponent uses as its source for returning the component pointers. Naturally, this means the fixup process fails to find ancestor forms.

As for the failure to initialize the global variable for the form or data module, well, that just happens. I don't know why, but it's a lot easier to fix that the fixup process.

Fixing The Problem

First, every form constructor should assign this to its global variable. For instance:

Account = this;

For the inheritance problem, there are two solutions.

  1. Level the inheritance so that all modules in the project are at the same level. In other words, if a data module is extended with a descendant, then all modules in the project must be extended with a descendant that uses the other extended classes. This is difficult and expensive, since the IDE will instantiate all ancestors of a descendant form, which can quickly spend you out of resources.
  2. Modify the FindGlobalComponent function.

Modifying Find Global Component

The following is the pattern for a basic modification of FindGlobalComponent. It goes in the project .cpp file.

TFindGlobalComponent OldFindGlobalComponent;

TComponent* __fastcall FindGlobalComponentExtended(const System::AnsiString Name)
{


if (Name == "Base1") return (TComponent *) (Base1 *) Special1;
if (Name == "Base2") return (TComponent *) (Base2 *) Special2;
return OldFindGlobalComponent(Name);


}

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{


try
{


Application->Initialize();

OldFindGlobalComponent = FindGlobalComponent;
FindGlobalComponent = FindGlobalComponentExtended;

...

In this example, the base class is represented by Base1 and Base2 - their descendants are Special1 and Special2 respectively.

Conclusion

This rather straightforward process can certainly be made simpler and more abstract. But the basic technique is sufficient to overcome this deficiency in form inheritance.

Copyright © 2004 by Mark Cashman (unless otherwise indicated), All Rights Reserved