kokoslolos 1 Posted Wednesday at 03:52 PM Hi, First of all, I'm not an expert in writing design time code, but this what I'm trying to achieve. I have my own custom TAction descendant, lets call it TXAction, with extra published properties (like ActionCode, ActionID, ActionName, ActionDescription ...), in design time time package that is installed in the IDE. Then I have a base form with some default TXAction components with some default properties set like ActionDescription with a place holder i.e "Export [fn] to xls" where the "[fn]" will be replaced in design time with the Form Name. In the TXAction Loaded overridden method, I have this code: procedure TXAction.Loaded; var aIXRBaseForm : IXRBaseForm; begin inherited; if (csDesigning in ComponentState) and (Owner<>nil) then begin if Supports(Owner, IXRBaseForm, aIXRBaseForm) then begin if ActionCode = ('.' + IntToStr(ActionID)) then ActionCode := aIXRBaseForm.FormCode + ActionCode; if (AnsiPos('[fn]', ActionDescription) > 0) and (aIXRBaseForm.FormName <> '') then ActionDescription := StringReplace(ActionDescription, '[fn]', aIXRBaseForm.FormName, [rfReplaceAll]); end; end; end; The code above works as expected, I have several descendant forms that inherit from this base form, and when I open them in the IDE, these inherited TXActions instead of the placeholder "[fn]" in the description, they are replaced with the Form's name. My problem is that the Save All button in the IDE is not activated for the form to indicated there was a change, like it does when a property is changed in the object inspector, so that the user can save it and store these changes in the .dfm. Although, if the Save button which is always enabled is clicked, the changes are saved! This leads me to thinking if I'm indeed doing this right, is this the correct way to change properties in design time? How can I make the Save All button enabled? Thank you. Share this post Link to post
msohn 29 Posted Wednesday at 04:11 PM A quick google search brought up this: https://stackoverflow.com/questions/31740385/vcl-events-handles-designer-modified So you can set Designer.Modified via the parent form - but checks for csDesigning and Designer <> nil are required. Also you should obviously set Modified only if you've actually modified something. Share this post Link to post
kokoslolos 1 Posted Wednesday at 04:29 PM I was planning to write this but I forgot, I use Delphi 2007. Does this solution work for this version of delphi? Share this post Link to post
kokoslolos 1 Posted Friday at 08:47 AM Another question, In case cases is the TForm Designer property nil? I'm trying to use this to notify designer that something us modified but it's always nil. Does it have to be run from an installed design package? Thanks! Share this post Link to post
msohn 29 Posted Friday at 08:51 AM 1 minute ago, kokoslolos said: I'm trying to use this to notify designer that something us modified but it's always nil. How did you verify this? Of course if you just run the code in an application of yours it will be nil. After you modified the code, you need to recompile the package which contains the code for the component and you need to make sure the IDE is actually using that modified version. If everything else fails, you need to debug the package by running a second instance of the IDE under the debugger. Share this post Link to post
kokoslolos 1 Posted 11 hours ago On 4/25/2025 at 11:51 AM, msohn said: How did you verify this? Of course if you just run the code in an application of yours it will be nil. After you modified the code, you need to recompile the package which contains the code for the component and you need to make sure the IDE is actually using that modified version. If everything else fails, you need to debug the package by running a second instance of the IDE under the debugger. Since I couldn't debug I used a simple ShowMessage code. I placed the code below in the "if Supports(Owner, IXRBaseForm, aIXRBaseForm) then" block that I posted in my original post. if Assigned((Owner as TForm).Designer) then ShowMessage('Designer is Assigned') else ShowMessage('Designer NOT Assigned'); And guess which message I get 🙂 🙂 . Can't understand why it's null, I did recompile the package of course, otherwise I wouldn't get the message dialog. Share this post Link to post
msohn 29 Posted 9 hours ago My guess would be that the Designer is not yet available when Loaded is called on your actions. Looking back at your initial post on what you actually wanted to achieve: why do you want to replace the placeholder at design time? Why not just do it at runtime? I.e. leave the action alone if csDesigning is set and only modify it at runtime. That seems the cleaner approach to me. Share this post Link to post
kokoslolos 1 Posted 5 hours ago It's probably what you said, the designer is not yet available. This is part of framework I'm working on, and every time I need a new form, that inherits from my base form class, I want the basic actions to auto complete as many properties as possible to automate the procedure and reduce time needed! Then, all this actions, the first time the owner form is opened, are saved in a database table, and with a security mechanism I have in place, I can control if a user has access to execute or not this an action, and also log its execution. And now as I'm writing this post, it just hit me that in my approach, if the FormName (custom property) is changed at design time, this cannot update my action's custom properties 😄 ! Need a bit of rethinking there. Share this post Link to post
msohn 29 Posted 4 hours ago I think the general approach of using form inheritance is not really suitable here, even though it might seem intriguing. In the past I've seen people write generators for this kind of work, make IDE extensions to create new specialised forms or just add preconfigured components from templates and anything between those extremes. I suspect for you it's more than just the actions, but for actions I once wrote a component editor for TActionList so I could invoke a little GUI at designtime which would then allow me to add a bunch of actions related to a custom component I had written. Maybe that's an option for you too. Share this post Link to post
Softacom | Company 9 Posted 3 hours ago 1 hour ago, kokoslolos said: It's probably what you said, the designer is not yet available. This is part of framework I'm working on, and every time I need a new form, that inherits from my base form class, I want the basic actions to auto complete as many properties as possible to automate the procedure and reduce time needed! Then, all this actions, the first time the owner form is opened, are saved in a database table, and with a security mechanism I have in place, I can control if a user has access to execute or not this an action, and also log its execution. And now as I'm writing this post, it just hit me that in my approach, if the FormName (custom property) is changed at design time, this cannot update my action's custom properties 😄 ! Need a bit of rethinking there. You can just override SetName method of your TBaseForm class and find your custom actions there and do all necessary updates. P. S. As mention kokoslolos, easiest way to develop designtime packages - debug it in other instance of Delphi. Share this post Link to post
Remy Lebeau 1573 Posted 58 minutes ago (edited) 4 hours ago, kokoslolos said: And now as I'm writing this post, it just hit me that in my approach, if the FormName (custom property) is changed at design time, this cannot update my action's custom properties 😄 ! Need a bit of rethinking there. I would suggest making the Action hold a pointer to the desired Form, and simply read the Form's current Name whenever needed. And if the Form's Name changes, then have the Form notify any Action that is pointing at it so they can use the new Name as needed. Easy to do if Actions register themselves with the Form so it can maintain a list of pointers to the Actions. Edited 57 minutes ago by Remy Lebeau Share this post Link to post