Delphi - Compound Components
Components that contain other Components

Creating components is covered in the related pages. However, sometimes it is useful to create a new component that contains several existing components. There are several ways to do this, each with its own pros and cons.

Though all the following work, and all of them show handles when selected, I prefer those that also display handles when several components are selected.

Note: Controls and Components are similar. Components can be displayed on forms at design time, but never when the program is running. Controls, derived from components, appear on forms at both design time and runtime.

Note: This page describes components that are composed of several components. This is different from the case where the designer adds several separate components to a form and then associates them using the Object Inspector.

Multiselect Handles | TFrame | TWinControl / TPanel | TCheckBox


Multiselect Handles

There are several methods that will allow you to create compound controls made of several existing controls. To some extent, they all work. However, most fail when multiple components are selected at the same time.

In general, if you click and drag with the mouse, a box will be displayed. When the mouse is released, all the components inside the box will be "selected". (Shift-click also works.) Delphi provides visual feedback by placing 4 grey handles (4 small grey boxes) on each of the corners of the selected components.

The problem is that the control's contents are rendered on top of the handles. To be clear, the handles are displayed on top of the parent control, but under the child controls. As a result, if a child control is placed in a corner of its parent, then that handle will not be displayed. Since these handles are 5x5 pixels, leaving a margin of 2 or 3 pixels between the subcomponents and the corners of the parent "fixes" the problem. Note that both panels and frames have this problem when their internal components are too close to the corners.

I only know one composite VCL control shipped to Delphi 5 - Samples/TSpinEdit - and it has this problem. However, since only a part of the right 2 handles is covered, they are still visible.

Unfortunately, since the handles appear to be rendered by the Delphi IDE, I am not sure how to fix this (or if it is even possible).


TFrame

The simplest way to create a composite component that contains multiple regular components is to use a TFrame.

Note that the 4 gray multiselect handles are covered if the components are at the edge of the frame. The solution is to leave a margin of 2 or 3 pixels between the subcomponents and the corners of the frame.


TWinControl / TPanel

It is possible to create new components based on TWinControl or a TPanel.

Disadvantages with respect to a TFrame

As with a TFrame - if the sub components are placed in the corners, they will be rendered on top of the grey handles normally displayed when multiple controls are selected. To fix this, simply make the bounding box either taller or wider than the contained components leaving a 2- or 3-pixel margin between the subcomponents and the corners of the container.


TCheckBox

Instead of using the generic TWinControl or a TPanel to contain multiple components, compound components can be derived from something more specific, like TCheckBox. This provides similar capabilities except that the handles are for the CheckBox component.

To correctly draw the subcomponents, particularly at design time, you will need to override Create, SetBounds, Resize, and AdjustSize.

Example code One alternative was to use GetParentForm to set the parent. Unfortunately, there are a few instances where this won't work (like when a control is placed on a panel or in a tab sheet).


AlignControls

Perhaps TWinControl.AlignControls (or TWinControl.AlignControl) is called at all the right times. If so, overriding just this one method would work (instead of including SetBounds and Resize). However, the code that calls this is fairly complicated and I am not sure that it would work in all cases.

Since I have decided to place sub-components outside the borders of the parent component, using just this method is probably inappropriate.


Author: Robert Clemenzi
URL: http:// mc-computing.com / Languages / Delphi / ComponentCompound.html