Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 17 total
Thread Parenting Control Descending to TElement ?
Wed, Mar 14 2018 9:12 AMPermanent Link

Mark Brooks

Slikware

Avatar

Maybe one for Tim, however:

Has anybody created a component within which there is an element which you would like to be the parent for dynamically created TControl descendants?

In my scenario I have a TBasicPanel descendant which has three "containers". The first and last of these contain a fixed number of items, so can be created via the interface. The middle "container" needs a variable number of items which themselves are TControl descendants. So my issue is, how to "parent" a TControl at runtime within a TElement acting as a container ...........

Any hints greatly appreciated
Mark
Wed, Mar 14 2018 10:11 AMPermanent Link

Matthew Jones

Mark Brooks wrote:

> TBasicPanel descendant which has three "containers"

Sounds rather like a TPanel then, which has borders and caption and a container for the children. No idea how it does it, but isn't there a new standard for the element called "Client" or something?

--

Matthew Jones
Wed, Mar 14 2018 1:31 PMPermanent Link

Mark Brooks

Slikware

Avatar

"Matthew Jones" wrote:

>>Sounds rather like a TPanel then, which has borders and caption and a container for the children. No idea how it >>does it, but isn't there a new standard for the element called "Client" or something?

It's more complex than that. The component that I've made has an element that acts as a container and I wish, at run-time, to add TControl descendants within that container, if that makes sense?
Wed, Mar 14 2018 4:54 PMPermanent Link

Mark Brooks

Slikware

Avatar

Mark Brooks wrote:

>>It's more complex than that. The component that I've made has an element that acts as a container and I wish, at >>run-time, to add TControl descendants within that container, if that makes sense?

So it looks like you can simply parent the Element of the Control descendent to the interface container element ....
Thu, Mar 15 2018 5:12 AMPermanent Link

Uli Becker

Mark,

>>So it looks like you can simply parent the Element of the Control descendent to the interface container element .... >>

Yes should be no problem. Just like a TListbox and ListItems.

I posted a TRadioGroup component that creates Radio Buttons within a client element. Same principle.

Cheers Uli
Thu, Mar 15 2018 11:22 AMPermanent Link

Uli Becker

I forgot to mention that you have to override the GetClientElement function:

protected
   function GetClientElement: TElement; override;

function TMyComponent.GetClientElement: TElement;
begin
   Result := FMySpecialClientElement;
end;

Additional informations in this thread:
https://www.elevatesoft.com/forums?action=view&category=ewb&id=ewb_components&page=1&msg=61#61

Cheers Uli
Thu, Mar 15 2018 12:00 PMPermanent Link

Mark Brooks

Slikware

Avatar

Uli Becker wrote:

>>I forgot to mention that you have to override the GetClientElement function .....

Thanks Uli. This actually looks really useful. Right now my approach may be a bit of a "hack". I am not overriding anything but rather, inside my "parent control" (a TBasicPanel descendant) I have this code to add a child into one of the parent's container elements:

                     P := TAPParticipantFormPanel.Create(Self);
                     P.Element.Parent := fMiddleContainerElement;

On the first line I'm creating a new instance of a TAPParticipantFormPanel control, which is itself a descendant of TBasicPanel. On the second line I'm wanting to "insert it" within an element of the parent control. It seems to work visually, however I was wondering when / how to free these newly parented children?
Thu, Mar 15 2018 3:03 PMPermanent Link

Tim Young [Elevate Software]

Elevate Software, Inc.

Avatar

Email timyoung@elevatesoft.com

Mark,

<< Has anybody created a component within which there is an element which you would like to be the parent for dynamically created TControl descendants? >>

Do you want to extend this functionality to design-time ?

<< In my scenario I have a TBasicPanel descendant which has three "containers". The first and last of these contain a fixed number of items, so can be created via the interface. The middle "container" needs a variable number of items which themselves are TControl descendants. So my issue is, how to "parent" a TControl at runtime within a TElement acting as a container ........... >>

The key is that each control can only have one "Client" element, and that client element is used as the parent for all child controls.  By default, the TControl.GetClientElement method simply returns the TControl.Element property, and this is sufficient for basic controls.

So, in your case, you'll want to override the GetClientElement method to make sure to return your middle container element, and when you create the container elements during the CreateElements method call in your control, be sure to take care to do so appropriately.  The TInterfacemanager.CreateElement method in the WebUI unit looks like this:

function TInterfaceManager.CreateElement(const AName: String;
                                        AParent: TElement=nil;
                                        const AClassName: String=ELEMENT_CLASS_DIV;
                                        AContainer: Boolean=False;
                                        AEvents: Boolean=False;
                                        ADynamic: Boolean=False): TElement;

(use it like InterfaceManager.CreateElement... where InterfaceManager is the global instance of the interface manager)

The keys here are the AContainer parameter, which should be True for your middle container if you want to allow controls to be added to it at design-time.  The AEvents parameter tells the interface manager that you want to receive design-time events for the element.  And, finally, the ADynamic parameter tells the interface manager that this class is created dynamically at design-time in the IDE and needs to be handled accordingly.  The TPage controls in the TPagePanel control have their ADynamic property set to True during base element creation.

Tim Young
Elevate Software
www.elevatesoft.com
Fri, Mar 16 2018 6:37 AMPermanent Link

Mark Brooks

Slikware

Avatar

Tim Young [Elevate Software] wrote:

>> Do you want to extend this functionality to design-time ?

Not at this stage Tim. The children are dynamically created at runtime.

>>The key is that each control can only have one "Client" element, and that client element is used as the parent for >>all child controls.  By default, the TControl.GetClientElement method simply returns the TControl.Element >>property, and this is sufficient for basic controls.

Understood.

>>So, in your case, you'll want to override the GetClientElement method to make sure to return your middle >>container element, and when you create the container elements during the CreateElements method call in your >>control, be sure to take care to do so appropriately.  The TInterfacemanager.CreateElement method in the WebUI >>unit looks like this:

Ok. That makes perfect sense. Can't quite believe that you'd actually considered this as part of the framework.

>>function TInterfaceManager.CreateElement(const AName: String;
>>                                         AParent: TElement=nil;
>>                                         const AClassName: String=ELEMENT_CLASS_DIV;
>>                                         AContainer: Boolean=False;
>>                                         AEvents: Boolean=False;
>>                                         ADynamic: Boolean=False): TElement;
>>
>>(use it like InterfaceManager.CreateElement... where InterfaceManager is the global instance of the interface >>manager)

I already override the CreateInterfaceElements of the parent TBasicPanel descendant and include the following code in there in order to setup the MiddleContainer correctly. Is this ok:

fMiddleContainerElement  := InterfaceManager.CreateElement(MIDDLE_CONTAINER_ELEMENT   , Element                 , ELEMENT_CLASS_DIV , True);

>>The keys here are the AContainer parameter, which should be True for your middle container if you want to allow >>controls to be added to it at design-time.  The AEvents parameter tells the interface manager that you want to >>receive design-time events for the element.  And, finally, the ADynamic parameter tells the interface manager that >>this class is created dynamically at design-time in the IDE and needs to be handled accordingly.  The TPage >>controls in the TPagePanel control have their ADynamic property set to True during base element creation.

Since I am only adding at runtime then I imagine these two parameters are not required?

And, finally, if I replace my original "hack" with the steps outlined above, can I iterate the Controls array of the parent such that it'll actually return the list of children added to the Middle Container (potentially by virtue of the GetClientElement override)?

Many thanks
Mark
Mon, Mar 19 2018 8:43 AMPermanent Link

Mark Brooks

Slikware

Avatar

Argh -- there DOES appear to be a problem with this approach however ......

If I override the GetClientElement per the suggestion, then I no longer receive touch / mouse events except within the MiddleContainer. The rest of the parent component is basically ignored.

I'm guessing this is because GetClientElement is used in some manner to determine whether these should be surfaced or not?

Anybody come across this before?

Thanks
Mark
Page 1 of 2Next Page
Jump to Page:  1 2
Image