aehimself 396 Posted October 15, 2022 Hello, Let's imagine the following scenario. I made a custom component which resides on a VCL frame. First of all, it's a lot easier to design something if you can see it (hence no TPanel) and some components require a form or a frame as a parent. It looks like this: Install it to the IDE and create a new application. Place this component on the form. Issue #1: You can not select individual components, any click with the mouse will select the whole frame instead. This is not a big thing, as you still can select its child components in the Structure pane. Now, save your project in an empty git repository and commit once, so you can compare the differences. Load up the project again, select the TEdit and enter something as it's Text property: Save your project again and check the differences in the DFM: Issue #2: All property changes in the components children are simply discarded. I can get around this one too by setting these in runtime, but it's less convenient that directly in the IDE. I suppose this is a limitation, I shouldn't design my custom component on a frame. How else can I achieve graphical designability in the IDE and how can I force for example a dxBarManager toolbars to stay within the components boundaries? I'm also interested about the reason why these things happen, if someone knows by heart. Cheers! Share this post Link to post
Stano 143 Posted October 15, 2022 I don't know the answer. But many programmers use Subform because of problems with Frame. They have no problem with that. Me neither. Maybe it's better to go the Subform route. Share this post Link to post
Lajos Juhász 293 Posted October 15, 2022 I have the same problem. The frame should be inline but I also have a frame that Delphi uses as object and then you cannot change the properties on the frame. I have no solution spent hours to research the problem. (You cannot just change the DFM). Share this post Link to post
Uwe Raabe 2057 Posted October 15, 2022 Can you show the code for the custom component? Share this post Link to post
Remy Lebeau 1394 Posted October 15, 2022 (edited) 5 hours ago, aehimself said: Issue #1: You can not select individual components, any click with the mouse will select the whole frame instead. You can add a message handler to the Frame class to handle the CM_DESIGNHITTEST message, setting the message's result to 1 if the mouse is over a child control within the Frame's client area. That will allow the child control to handle the mouse click. Edited October 15, 2022 by Remy Lebeau 1 Share this post Link to post
aehimself 396 Posted October 16, 2022 8 hours ago, Uwe Raabe said: Can you show the code for the custom component? Sure. There is no code whatsoever: unit TempComponent; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls; type TMyTempComponent = class(TFrame) Edit1: TEdit; Button1: TButton; RadioGroup1: TRadioGroup; private { Private declarations } public { Public declarations } end; Procedure Register; implementation Procedure Register; Begin RegisterComponents('Temp component', [TMyTempComponent]); End; {$R *.dfm} end. Share this post Link to post
Attila Kovacs 629 Posted October 16, 2022 just being the smart*ss, why are you mixing composite components with frames? can't you just put a frame onto an another frame? Share this post Link to post
aehimself 396 Posted October 16, 2022 4 minutes ago, Attila Kovacs said: just being the smart*ss, why are you mixing composite components with frames? can't you just put a frame onto an another frame? This is why 🙂 12 hours ago, aehimself said: I suppose this is a limitation, I shouldn't design my custom component on a frame. How else can I achieve graphical designability in the IDE and how can I force for example a dxBarManager toolbars to stay within the components boundaries? Share this post Link to post
Attila Kovacs 629 Posted October 16, 2022 @aehimself I don't get it. I just created a new VCL Form Application plus designed two new frames, then added frame2 to frame1, without creating a custom component. What is the concept behind creating a compound component from a frame? You can also add code to the base frame and override it in the other places. I don't know any Bar Managers except Gunther, but to make a component fill up a given space is normally done with alignment. Share this post Link to post
aehimself 396 Posted October 16, 2022 13 hours ago, Remy Lebeau said: You can add a message handler to the Frame class to handle the CM_DESIGNHITTEST message, setting the message's result to 1 if the mouse is over a child control within the Frame's client area. That will allow the child control to handle the mouse click. I'm experimenting with this but I can not seem to get it to work. procedure TMyTempComponent.HitTest(Var Msg: TCMDesignHitTest); begin // ShowMessage('Edit1.BoundsRect.Top: ' + Edit1.BoundsRect.Top.ToString + sLineBreak + // 'Edit1.BoundsRect.Left: ' + Edit1.BoundsRect.Left.ToString + sLineBreak + // 'Edit1.BoundsRect.Bottom: ' + Edit1.BoundsRect.Bottom.ToString + sLineBreak + // 'Edit1.BoundsRect.Right: ' + Edit1.BoundsRect.Right.ToString + sLineBreak + sLineBreak + // 'Msg.XPos: ' + Msg.XPos.ToString + sLineBreak + // 'Msg.YPos: ' + Msg.YPos.ToString); If PtInRect(Edit1.BoundsRect, Point(Msg.XPos, Msg.YPos)) Then Msg.Result := 1 Else Msg.Result := 0; end; The event does not fire at all if I move the cursor over any child component (Edit, button or radiogroup) only when it is over the frame itself. I also tried adding ControlStyle:= ControlStyle - [csDesignInteractive]; in the constructor. I'll keep trying, but am I on the right track here? Maybe frames are just work... different? 🙂 Share this post Link to post
Pat Foley 51 Posted October 16, 2022 I never had good luck with Frames... With custom component development the issue is the IDE needs a restart after an "improvement" to the control. Or uninstall the control and reinstall once you have a project group set up. to rebuild the control. In the IDE control X and control V the control to reflect the improvements. For a complex control I simply use a form that keeps all the controls events assigned. By wrapping the form create with owner and parent and Event arguments the "Parent form" is not added to uses clause. rule 1 Do not use ShowModal that is the only danger I have found. constructor NewAux(const aName:string; bossForm: TForm; APanel: TWinControl; aEM: TEventBoss; Headings: Tstrings; aClick: TnotifyEvent; Settings: TWindowFormSettingSet); Example code. Share this post Link to post
Uwe Raabe 2057 Posted October 16, 2022 19 hours ago, aehimself said: I made a custom component which resides on a VCL frame. I guess, that is not one of the use cases the developers had in mind when they designed the custom component system. AFAIK, you can either have subcomponents created dynamically with their properties stored as sub-properties of the outer component or you can have a frame stored in the object repository with derived instances in your project. Share this post Link to post
Remy Lebeau 1394 Posted October 17, 2022 On 10/16/2022 at 6:38 AM, aehimself said: If PtInRect(Edit1.BoundsRect, Point(Msg.XPos, Msg.YPos)) Then The message's coordinates are expressed as screen coordinates, but a control's BoundsRect is expressed as client coordinates within the parent's client area. So, you would need to normalize the two sets of coordinates to the same coordinate space before you can compare them. Also, it turns out that TWinControl already handles CM_DESIGNHITTEST, by forwarding the message to any child control that is at the specified coordinates. By default, TControl returns 0 for the message's result. So, another option may be to have your Frame class subclass its child controls and have them unconditionally return 1 for CM_DESIGNHITTEST, instead of handling the message at the TFrame level. Just a thought. On 10/16/2022 at 6:38 AM, aehimself said: I also tried adding ControlStyle:= ControlStyle - [csDesignInteractive]; in the constructor. That flag only affects right mouse clicks, by converting them into left mouse clicks. On 10/16/2022 at 6:38 AM, aehimself said: Maybe frames are just work... different? 🙂 Maybe. I've never tried to make a component out of a Frame before. Have you tried basing the component on TPanel instead? Share this post Link to post
Paul TOTH 2 Posted October 17, 2022 the purpose of TFrame is to not register a custom component ! you create a frame, put some components, and voilà you can put this frame on any form of your project without registering anything. when a custom component owns some subcomponents, there's more to do - that I don't have in mind yet - to support serialization to/from the DFM Share this post Link to post
Uwe Raabe 2057 Posted October 17, 2022 1 hour ago, Paul TOTH said: when a custom component owns some subcomponents, there's more to do - that I don't have in mind yet - to support serialization to/from the DFM I don't know if all is necessary, but I at least it is sufficient: have a field for the sub component exposed as a published read-property create the instance in the constructor (Self as Owner is allowed omitting the Free in the destructor) call SetSubComponent(True) after creation set all properties as needed don't forget to set Parent Share this post Link to post