Jump to content

Incus J

Members
  • Content Count

    157
  • Joined

  • Last visited

Posts posted by Incus J


  1. OK, I think I've understood (hopefully :).  If I free a form or data module manually in code, then its associated OnDestroy event fires.  But if the user closes the application, then OnDestroy events for auto-created forms and data modules are bypassed: The application simply terminates and relies on the OS to clean up any allocated memory.

     

    On 6/20/2022 at 6:12 PM, SwiftExpat said:

    I ended up with a timer to save state every x seconds 😞  Maybe someone else has a better solution.

    I've noticed that a form (but not a data module) has an OnSaveState event in the object inspector.  Documentation indicates it is fired when a form is about to close.  If that completes before the app terminates, it might be a good place to save preferences/state etc. and clean up.


  2. Thank you!  It looks a little bit over my head at first glance - but I will have a good look through it.  Perhaps I also need to have a look at the equivalent TPlatformWindows Terminate procedure and compare with the macOS Cocoa one to see how they differ.

     

    Naive question:  If they expect you to implement the form destruction event manually, what is the actual purpose of the OnDestroy event property in the object inspector?


  3. Instant termination sounds like a (fairly major?) bug.  If Exiting an app simply kills the process, nothing will get freed, preferences won't save etc. - so I'd need to free everything manually in the main form's Close event perhaps.

     

    Did you submit a bug report on the quality site?  If yes, and you have a link to the report I can vote for it I think.


  4. The overall size of the form may vary from platform to platform (e.g. sizes of titlebar and border differ between Windows and macOS, and may differ between OS versions too).  So at design time you don't necessarily know what the overall width of the form will be.  It would make sense for Delphi to use width of the client area - since that value is known at design time.

     

    If width is client width, then it would make sense for minwidth to be minimum client width also, so everything matches nicely - but I don't know whether that is the case.  If not, and minwidth is using the full width of the form, while width isn't, that seems unfortunate.  I believe minwidth is a new property for FMX in Alexandria though - perhaps it could use a tuneup.

     

    Just a workaround thought:  If minwidth is including titlebar and border areas in its calculation, the RTL must have access to that all encompassing value, so your app may be able to query values once it is running, and set appropriate constraints at runtime, rather than design time.  The documentation has entries for both FMX TForm width and clientwidth properties, so you may have more options to play with at runtime.

    • Like 1

  5. Thanks SwiftExpat - the app is running on macOS (deployed by the IDE when I click run).  The IDE is running in a Windows VM on the same system (Fusion).  Yes, compiling is set to Debug - and I can place breakpoints in other methods, such as DataModuleCreate, and that works OK - the app pauses at that point.  So breakpoints in general are working.  But when I place a breakpoint in DataModuleDestroy - and then Exit, the app simply closes without pausing at the breakpoint.  The breakpoint marker gets a green tick when the app is run, which I think is an indication of a valid breakpoint.

     

    So my guess is the DataModuleDestroy procedure is not entered during Exit - so perhaps the associated OnDestroy event isn't occurring (speculation).  I posted thinking I must have missed something obvious - and that may well be the case.  I'll try setting up the same thing in a new empty project next, see whether I encounter the same behaviour again.


  6. OK I'll try - the project file looks like this:

    program ProgramName;
    
    uses
      System.StartUpCopy,
      FMX.Forms,
      uiMain in 'Code\uiMain.pas' {MainForm},
      …
      dm1 in 'Code\dm1.pas' {DataModule1: TDataModule},
      …;
    
    {$R *.res}
    
    begin
      Application.Initialize;
      Application.CreateForm(TMainForm, MainForm);
      Application.CreateForm(TDataModule1, DataModule1);
      Application.Run;
    end.

    So a main form and the data module are created at startup.  That's it really.  I'm not manually freeing the data module - I think it is owned by the Application, so will be freed automatically when the Application is terminated (?)

     

    The data module itself has two event handlers assigned:

    OnCreate	DataModuleCreate
    OnDestroy	DataModuleDestroy

    The OnCreate (DataModuleCreate) is working OK.  The code in DataModuleDestroy is shown in my initial post above.  I can work around it by calling my CleanUp routine via the main form's OnClose event instead, but puzzled.

     


  7. I have a TDataModule unit in an FMX app, which is auto-created when the app start up (I'm not creating it manually).  When the app exits, I'd like a cleanup routine to execute.  I've added this in an OnDestroy event handler for the Data Module, like this:

    procedure TDataModule1.DataModuleDestroy(Sender: TObject);
    begin
      Cleanup;
      end;

    But as far as I can tell my Cleanup routine is not called.  So I've placed a breakpoint on the 'Cleanup;' line above.  When I run the app the breakpoint red circle gets a green tick - so I think the breakpoint itself is valid and live.  When I quit the app, it simply closes - the IDE does not stop at the breakpoint.  Does that imply that the Data Module OnDestroy event is never triggered?

     

    Do I need to set anything special for the OnDestroy event to be called on an auto-created TDataModule?

     

    (I've had a look through the source for TDataModule in System.Classes - there is a call to FOnDestroy in a DoDestroy routine, but I'm not sure of the destruction sequence, as there's also BeforeDestruction and Destroy methods)


  8. Oh - I can reproduce this issue in a clean empty project:

     

    - Create a new FMX project with a single main form.

    - Add a new datamodule unit to the project.

    - Next add a non-visual FMX TActionList to the datamodule, and also add a TAction for good measure.

    - Save the project, Close All, then reopen the project, and open the datamodule in the editor.

     

    No problems so far.  Now in the data module .pas file, I add a single item to the implementation uses statement, like this:

    implementation uses FMX.Dialogs;
    
    {%CLASSGROUP 'FMX.Controls.TControl'}

    I've added FMX.Dialogs here, but it can be any unit.

     

    - Save, Close All, then reopen the project, and try to open the datamodule = Boom!

     

    As soon as the implementation section gets a uses statement, the {%CLASSGROUP} pseudo-property is no longer read by the IDE when opening the module (?).  As a result the datamodule gets misinterpreted as VCL (?)

     

    Or maybe I'm just really tired.  Can anyone confirm?

     


  9. OK the ClassGroup property does not seem to be stored in the .dfm file.  There's something special about this property - documentation describes it as a pseudo-property.  Instead the assigned value is stored as a declaration in the accompanying .pas file:

    {%CLASSGROUP 'FMX.Controls.TControl'}

    So I think the IDE should be able to determine from that declaration that the controls on the data module are FMX.  But it's not doing.  I must have overlooked something.


  10. Only this one project open.  As a quick test I've also tried opening it up in an earlier version of Delphi (10.4.1) and got the same behaviour.  The main application form seems OK.  Just this one Data Module unit is getting misinterpreted as VCL.

     

    I'd like to try setting the unit's ClassGroup property (but without opening the unit, since by then it's too late).  If I've understood how Data Module's work, ClassGroup determines whether the module supports FMX or VCL controls.  Supported values are: System.Classes.TPersistent (Framework neutral), Vcl.Controls.TControl, FMX.Controls.TControl.  I'm guessing I'd want the latter.

     

    There's no mention of a ClassGroup property in the text of the module's .dfm file at present (is that normal?) - but could I add it manually with a text editor somehow?  I'd need to figure out where to insert it, and ensure I get the formatting correct though.


  11. I'm struggling to open a previously saved Data Module unit that is part of an FMX project.  The module contains an FMX TActionList.  

     

    When I attempt to open the project, the IDE automatically adds two extra VCL units onto the module's uses statement, like this:

    uses
      System.SysUtils, System.Actions, FMX.ActnList,
      FMX.Dialogs, FMX.StdActns, System.Classes,
      Vcl.StdActns, Vcl.ActnList;

    ...even though it's an FMX Action List.  I don't know why it is adding those two VCL items - I can remove them manually from the uses statement, but they reappear.  If I switch from Code to Design view, the IDE protests:  "Error reading actionname.Text: Property Text does not exist" (with options to Ignore/Cancel/Ignore All).  If I choose Ignore All, the Text property is stripped from all my existing actions, and replaced with an empty Caption property.

     

    It seems to be a bit confused - as though it is reading the FMX Actions and ActionList from the .dfm file, but then attempting to instantiate them as VCL Actions instead.  I'm aware that there is a ClassGroup property for Data Module units, and wonder if this has not been saved?  Note that everything was working OK prior to closing the project and then re-opening it.

     

    How might I resolve this, as the IDE seems to corrupt the unit every time I open it (though I can revert using History), and as a result the project no longer compiles?


  12. Der schöne Günther mentioned context.  A couple of questions come to mind that might help in homing in on the issue:

    On 6/9/2022 at 3:05 PM, msd said:

    I have one big project and I migrated it from older versions of Delphi to the latest Delphi 11.1

    Did you run the Delphi 11 IDE in HiDPI mode while migrating the VCL project?  (Is your own development environment HiDPI?)

     

    On 6/9/2022 at 3:05 PM, msd said:

    When I start the app on a computer which has activated zoom over 100% (High-DPI screen)

    Which version of Windows is that computer running (e.g. 7, 8, 10, 11) ?


  13. On 6/3/2022 at 10:57 AM, softtouch said:

    I will then just save them into a folder inside the user folder and execute them there.

    In macOS there is a folder:

    Users/(User Name)/Library/Application Support/(App Name)/

    It seems to be a recognised spot for storing config, preferences, cache data, sqlite files.  I don't know whether that's a good place for an addon executable, but might be worth a look if you don't want your folder to be too obviously user visible.

     

    There's a stack overflow post looking at this from a user config point of view:

    Where do OSX applications typically store user configuration data?

     


  14. Yes - if Per-Monitor v1 is supported then that makes sense.  But I think Delphi only supports Per-Monitor v2, which was introduced in the Windows 10 Creators Update (1703).

     

    Windows 7 failed to scale down my VCL app when I tested - but I haven't tested it in Windows 8.


  15. I've successfully reported the issue here:

     

    RSP-38478 : IDE mangles unit paths causing Code Insight, Error Insight and Find Declaration to fail

     

    A little tricky to report as the quality website also mangles my example paths - but differently (the paths looks OK in the editor prior to submission, but once submitted the report is displayed with some backslash characters removed from the paths).


  16. For VCL, be aware that this High DPI setting in options can impact how your VCL application forms render when you run the app in older versions of Windows (e.g. Windows 7).  I think older versions of Windows can not handle the change of DPI setting, since, for VCL, the IDE actually stores the scaled form and control values (left/top/width/height).  Should be OK if your app is only intended for Windows 10 and up.


  17. Thanks SwiftExpat - I'll have a go at your work around.  I've never created a symbolic link before.

     

    I'm struggling to report the issue.  I've logged in OK and got the report all typed up in the form, with steps to reproduce, but when I click Create, the form will not submit:

    You do not have permission to create issues in this project.

     

    The project defaulted to RAD Studio (RSP) which sounds correct, but the only options available to me in the dropdown menu are:

    Community Site (CMP)

    Interbase (IBP)

    xxxxxxxxxxxxxxxx

     

    Hmm...  I could try selecting xxxxxxx?


  18. I might just have confirmed it.  For a unit path like this:

    C:\Path\+Library\+Folder\unit.pas

    The IDE Find Declaration command reports: 

    Cannot open file "C:\Path\ Library\ Folder\unit.pas"

    Notice that the IDE has mistakenly converted all the + characters in the path to spaces.  As though it has accidentally fed the path through a URL decoding routine, which has mangled it.  (In URLs, spaces are often encoded as + characters, but not in Windows file paths).

    • Thanks 1

  19. I think I'm encountering an issue with Delphi 11 Code Insight.  In the Structure pane I'm seeing a lot of F2063 errors, like this:

     

    F2063 Could not compile used unit 'some unit' at line x (x:y)

     

    The app compiles and runs fine.  If I examine the source code, the declaration of the offending units in the uses statement are underlined in red, and Find Declaration fails.  It's as though the IDE (Code Insight/Error Insight) simply can't locate the files in question to compile them, hence the errors, but the compiler itself has no problem.

     

    This seems to be happening to units that are stored on a path that contains a '+' (plus) character in folder name.  The path is a valid Windows path, and these units have been in a folder named like this for years, and used in many Delphi projects.  So I suspect a recent bug in the way Code Insight/Error Insight parses the paths of used units (?)

     

    If I simply rename folders to remove the (potentially) offending character, other existing projects that use these units will break, so I'd like to avoid that.

     

    Since I'm unsure, I thought I'd ask:  Does anyone know whether the Delphi 11 IDE has an issue with certain characters in folder names?

     


  20. Thank you David - that approach sounds very promising.  I've never considered data modules before (I probably made an assumption it was something to do with databases) - so I'll go and have a play around with that idea.  I'm guessing from your description that the Object Inspector will become aware of, and let me select actions I've defined in a separate data module - providing I add the data module to the main form's 'uses' section?

     

    Attila, yes you're right - I think it's that the form unit interface section is already populated with numerous entries for all the components I've added to the form.  If I start adding my code or classes in this unit, it feels cluttered - but that's maybe just a perception on my part.  (I know that when I came to convert an older VCL project to FMX, application code written directly in the VCL form handlers proved time consuming to extract.)  I was kind of hoping for a non-visual TController organisational component that I could then assign to controls to indicate to the IDE "create your event handlers in here instead".  David's suggestion above, using a separate data module and action list, sounds like it might give me something close to that.

     

    Pat, do you mean create my controller classes on a secondary form (instead of in a plain unit)?   I'm not sure whether I've understood you fully - could you elaborate?


  21. I’d like to assign event handlers to visual components on a form at design time as usual (for example by double-clicking a popup menu item’s OnClick event, or selecting an Action via the Object Inspector), but I don’t want the IDE to create the handler in the form unit itself.  I find the form unit quickly becomes cluttered and difficult to maintain.  Instead I think I’d like the IDE to create the handler in a separate controller class in another unit.

     

    Basically I’m trying to separate UI from code, but still be able to assign the event handlers rapidly at design time.  Can't quite figure it out.  I’m happy to use Actions and ActionLists if that helps - in fact that might be preferable.

     

    In the past I’ve ended up with reams of tiny procedures in the form unit that simply hand off to a controller to perform the actual task (and quite often the controller class itself then simply passes-the-buck on to the model) :

    procedure TForm1.SomeAction(Sender: TObject);
    begin
      TController.ActuallyPerformThisAction;
    end;
    
    …elsewhere…
    
    class procedure TController.ActuallyPerformThisAction;
    begin
      TModel.WellReallyThisIsYourJob;
      UpdateTheUIToReflectModel;
    end;

    In complex apps I can create multiple controller classes to handle different aspects of the app and keep things organised, which is good.  But writing multiple handlers that simply pass-the-buck seems inefficient - I feel like my time could be better spent somehow, and my code also becomes cumbersome to navigate through:  Getting from a UI control to some code that actually does something involves several ‘Find Declaration’ steps.

     

    I’m not sure I’ve explained this well, but assuming it is possible to fathom what I’m driving at, what’s a better/good way to achieve UI/code separation while maintaining rapid development in the IDE?


  22. On 4/13/2022 at 9:23 AM, egnew said:

    I set the password using:

    document.getElementById("passwordInput1").value = 'mypass'

     

    I click the button using:

    document.querySelector("input[type=submit]").click();

    Can you post your Delphi code that you are using to execute those two lines of script?

     

    document.querySelector returns the first submit button, which might not be the one you are wanting to target (the page could potentially contain more than one form).  If the ID is known you could try targeting the button in a more specific way:

    document.getElementById("text_i18n.authframe.safr.button.openonline").click();

     

    Thought:  ExecuteScript may be asynchronous, so you may need to combine the two lines of script to execute as a single statement - I don't know your existing code, but something like:

     

    s := 'document.getElementById("passwordInput1").value = "mypass"; document.getElementById("text_i18n.authframe.safr.button.openonline").click();';

    Browser1.ExecuteScript(s);

     

×