From: Allen Bauer <abauer@borland.com>
Subject: RE: [delphi] New component challenge
Date: Fri, 7 Jul 1995 21:31:01 -0700

----------
From: 	The Nomad[SMTP:tnomad@digital.net]
Sent: 	Friday, July 07, 1995 6:02 PM
To: 	delphi-talk@bridge.net
Subject: 	Re: [delphi] New component challenge

>Is there anyone out there than can help give me a start?
>I've been able to create a component that is a line and can
>receive the OnClick event. However, it seems that there is a
>bounding rectangle around the line that receives the OnClick
>also. I want the user the have to select the line specifically,
>not some bounding area (what if two lines intersect? their 
>bounding areas will intersect and only the top one would receive
>OnClick).

On this, I have been very unsuccessful creating a TLine component.
A fellow developer and I puzzled over this some time ago, and determined
that we couldn't do it in a satisfactory manner.  The main problem is that
Delphi is (or seems to be) hard-coded to present controls in a rectangle.
There isn't any way to 'tell' Delphi that the only object handles to draw are
at the beginning and the end of the TLine

>If you can help me out then THANKS! I have one more question. 
>Given I can create the component above, how do I provide the 
>capability for a TImage (or some variation of) to hold any number
>of these components?

This one is easy.  Use a TList to hold your components.  If I understand the
requirements, each line would be like:

type
        TLine = class(TGraphicComponent)
                private
                        FStartX: Integer;
                        FStartY: Integer;
                        FEndX: Integer;
                        FEndY: Integer;
                        FLabel: String;
                        FPen: TPen;
                protected
                        constructor Create(AOwner: TComponent);
                published
                        property StartX: Integer read FStartX write
SetStartX default 0;
                        ...
        end;


Note however that TGraphicComponent comes with a Canvas, and also
comes with the Left/Top/Width/Height baggage.

************************************
*           The Nomad              *
*        tnomad@digital.net        *
************************************
------------------------------------------------------------------
You're on the right track by using a TGraphicalComponent as the starting point.  The missing link I think you want is the CM_HITTEST message.  This is sent by the container of the graphical component.  Since there is no window handle, Windows can't do it.  In order to only get a Click event fired when the user clicks on or near the line, simply return 1 in the Result field of the TCMHitTest (The definition is the same as TWMHCHitTest) record.  If you return 0, the control will try the next control in Z-Order.  If no other controls are found the container (TPanel, TForm, TGroupBox, etc...) with get the click.  You should be able to go ahead and use the standard Canvas and bounds properties that are provided by the TGraphicControl component.  Also be sure to exclude csOpaque from the ControlStyle set property so that it will appear transparent. (I don't think it's set by default, so nothing is is required)

The CMHitTest message handler would be declared as:

procedure CMHitTest(var Message: TCMHitTest); message CM_HITTEST;

Hope that provides the "missing link" for you.  The forms designer will *always* select using the entire rectangle.   I've captured this as an issue for consideration for future Delphi releases...(no promises... ;-).

Allen Bauer.
Delphi R&D
Borland International, Inc.
