2008. január 20., vasárnap

Accessing a TForm from a package


Problem/Question/Abstract:

I have a package which contains a form and some units. I want to be able to load that form into a main application but I have no idea how to do it does anyone have some example code I can look at?

Answer:

There are two ways to use packages: statically bound or dynamically loaded. This is similar to DLLs. To bind a package statically to your project you name it in the projects package list and build the project with run-time packages.
To use something from the package you simply add the unit that contains the something to a uses clause as if it were part of the project. The linker takes care of making sure the unit is not compiled into the project but linked in from the package at run-time. In this scenario the code using the package is completely unaware that the stuff it uses comes from a package.

Dynamically loaded packages are somewhat more complex to use. The following is an excerpt from an older reply on how to put MDI children into packages. Note that you need to build the host app with run-time packages, you just use only the standard set of packages, do not name the packages you want to load dynamically in the package list.

Quote:

If you load them dynamically via LoadPackage the main program typically gets a list of available child form packages from somewhere, e.g. from an INI file, a registry key, or simply by scanning a folder at a known location for BPL files. Each package is required to export a set of functions with known names (perhaps only one). You export functions from a package the same way you do it from a DLL, via an exports clause. And you get these entry points from your main program also the same way you do it for DLLs, via GetProcAddress. So each child form package would export a function

function CreateChild: TForm;

The main app can now create child forms just by calling this function for each childform package. Whether it uses the returned reference is up to the program, it can get references to the child forms from mainform.MDIChildren if it needs them. Each child form in turn is required to implement a specific interface which the main form can use to communicate with it. This interface can be message-based, or it can be an actual Interface (non-COM) which the main form can obtain by sending a specific user message to the child form. This way the main form needs to know no details about the child forms, so has no need to Use the child forms unit.

If you don't load the packages dynamically you can still remove the dependence on the child form units completely. In this case the CreateChild method would be something the package exports in a unit (one unit per package, it may contain only this one function) and the main form would Use this unit from each of the packages. This is of course not very maintenance-friendly, there are other ways to manage this, e.g. by using a central registration mechanism (implemented in a common package) into which each of the child packages can register its CreateChild function together with the package name. The main form could then ask this registry to create a child for a given package. If the main form reads the list of packages from some file this would make your package set extensible without requiring any change to the main form when you add a new one.

Nincsenek megjegyzések:

Megjegyzés küldése