Jump to content

Incus J

Members
  • Content Count

    157
  • Joined

  • Last visited

Community Reputation

10 Good

Technical Information

  • Delphi-Version
    Delphi 11 Alexandria

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Incus J

    Interface Reference counting

    No. It would not return anything at all, because the parameter is being passed in by value, not by var reference. Ah - so that is a key difference to, for example, passing in an parameter of type TStringlist - even without 'var' I think an object such as TStringlist gets passed by reference (?)
  2. Incus J

    How to set FMX TWebBrowser UserDataFolder?

    A global setting sounds promising. FMX.WebBrowser.Win.TGlobalEdgeBrowserSettings.UserDataFolder:='(my path)'; That's giving me an error of Undeclared identifier TGlobalEdgeBrowserSettings at the moment. That class doesn't seem to be present in the FMX.WebBrowser.Win unit. I'll have a look around for it elsewhere - maybe it's moved in 11.3?
  3. Incus J

    Interface Reference counting

    So much to learn - and so many opportunities to make mistakes that will still compile while unwittingly shooting myself in the foot 🙂 I didn't even know an untyped var parameter was permitted - in my specific case it would be typed, as below, but I can see myself doing something like accidentally specifying a type of TMyInterface instead of IMyInterface due to a momentary distraction, tiredness or loss of focus. Yes, sorry - that's a typo on my part, should have been: if SomeclassInstance.CreateAndReturnAnObject(MyObject) then begin My understanding now is that the first version of the declaration below (with var) would successfully auto-reference count and retain MyObject on return, whereas the second version would end up returning (a pointer to?) an instance of MyObject that had just been freed: function TSomeclass.CreateAndReturnAnObject(var MyObject:IMyInterface):boolean; begin MyObject:=TMyInterface.Create; result:=true; end; //MyObject retained. vs function TSomeclass.CreateAndReturnAnObject(MyObject:IMyInterface):boolean; begin MyObject:=TMyInterface.Create; result:=true; end; //MyObject vapourises here. When an interfaced object (e.g. MyObject) goes out of scope and is automatically freed, does it get nil assigned to it, or does it behave the same as non-interfaced objects which keep a dangling pointer to the freed instance after SomeObject.Free (unless SomeObject.FreeAndNil is used to free it)?
  4. Incus J

    Interface Reference counting

    Thank you - that's a good clear explanation. I'll have a go at your suggestion and step through with the debugger to see what actually happens. That does make sense, though I like to have a boolean return value to test success against in a compact way: if TSomeclass.CreateAndReturnAnObject(var MyObject) then begin vs MyObject := TSomeclass.CreateAndReturnAnObject; if Assigned(MyObject) then begin ...but perhaps there's a better approach?
  5. I'm reading up on interfaces, and trying to understand when a reference counted object will be freed. var MyObject:IMyInterface; begin if TSomeclass.CreateAndReturnAnObject(var MyObject) then begin //Do something with MyObject end; end; //MyObject is freed automatically here? If CreateAndReturnAnObject creates an object of type TMyInterface (which implements IMyInterface) and returns it via the MyObject parameter, will the object still exist immediately after CreateAndReturnAnObject returns - or will it have fallen out of scope? How about if I omit 'var' from the parameter? Since MyObject starts of as nil, I'm guessing it can't have its reference count auto-incremented until after it is created, so will it cease to exist once CreateAndReturnAnObject completes, in which case I can't 'Do something with MyObject', or does the compiler know to keep it around somehow?
  6. Incus J

    How to set FMX TWebBrowser UserDataFolder?

    Yes, with VCL TWebBrowser EdgeUserDataFolder defaults to a path beginning with %LOCALAPPDATA%...etc... and this can be customised. Unfortunately with FMX TWebBrowser the default seems to be the folder of the app executable instead. So I'm trying to find a way to surface and set the underlying UserDataFolder property (defined in TEdgeBrowserHelper) for an FMX TWebBrowser. That way I can: Set the FMX TWebBrowser engine to IEOnly at design time At runtime my app can set Edge UserDataFolder to my new desired (writable) path - and only then: Switch the engine to EdgeOnly so it will initialize WebView2 with my new path. I'm not sure how to (re-)call it. Note that as things initially stand it will not have been called successfully yet.
  7. Incus J

    How to set FMX TWebBrowser UserDataFolder?

    If I subclass FMX.TWebBrowser e.g. TWebBrowserPlus=class(TWebBrowser) can I surface and access Private member FWeb ? I thought perhaps I could simply redeclare FWeb like this: type TWebBrowserPlus=class(TWebBrowser) private FWeb: ICustomBrowser; //redeclare private ancestor field to surface it in my subclass...? ...but that doesn't seem to work.
  8. Incus J

    How to set FMX TWebBrowser UserDataFolder?

    That would make sense. So far I've navigated: TWinNativeWebBrowser.CreateHandle calls TWinNativeWebBrowser.CreateWebView which calls TWinNativeWebBrowser.InitializeWebView which calls CreateCoreWebView2EnvironmentWithOptions I've yet to find the bit where FMX.TWebBrowser calls TWinNativeWebBrowser.CreateHandle - but there must be a connection between those two somewhere. I've noticed there's a TEdgeBrowserHelper = class helper for TWinNativeWebBrowser which has: property UserDataFolder: string read GetUserDataFolder write SetUserDataFolder; ...that's the property I'm after I think. Now I need to figure out how to access that property from my FMX application, when all I have is my instance of FMX.TWebBrowser on a form. Could I do something like TMyWebBrowser=class(TWebBrowser) and then cast TMyWebBrowser(WebBrowser1) to get at its internals?
  9. TWebBrowser and TEdgeBrowser VCL components have a property named UserDataFolder/EdgeUserDataFolder which sets a folder for the Edge engine (WebView2) to write session data. TWebBrowser FMX component does not expose this property, and the component defaults to using the app executable folder to write session data. That default value is problematic because the Program Files folder where the app is installed to is not writable. So I need to set a different location. I know the UserDataFolder property is in there somewhere, so I'm hopeful that I can surface it somehow. But I'm having trouble navigating through the FMX.WebBrowser code since it branches and calls services depending on the platform and engine - FindDeclaration only gets me so far. How can I access and set the Edge UserDataFolder when using the FMX TWebBrowser component?
  10. Incus J

    Puzzled by StrToDate

    Thank you for the suggestions and code example - I will have an explore. Yes I agree TStringlist is slightly heavy for the job - though I do find it useful when stepping through code in the debugger as there is a visualiser to display the contents. I started out with a dynamic array, but got confused trying to pass the array into and out of subroutines, and the TArray type seemed to lack useful methods such as myArray.IndexOf ...basically my lack of experience with arrays led me to switch to TStringlist to save time! My main reason for rolling my own is that I've discovered the built in StrToDate function differs in behaviour between Delphi versions - so I want to create my own function that I can rely on to maintain the same behaviour going forward.
  11. Incus J

    Puzzled by StrToDate

    Yes - at the moment I have a private InitialParse subroutine that basically attempts to grab three date components from whatever string it is fed, and drops them into a TStringlist (e.g. from 'Feb 7th, ''23' it will extract 'Feb' and '7th' and '23'). What to do with those three components (how to interpret them) is decided later. It works, but if necessary this subroutine could be made much stricter in terms of what it will accept as input. class procedure TDateUtils.InitialParse(s: string; var ts:TStringlist); {Pull three components from the date string.} var i:integer; c:char; bSkip:boolean; sPart:string; begin sPart:=''; bSkip:=true; for i:=1 to Length(s) do begin c:=s[i]; if c.IsLetterOrDigit then begin if bSkip then begin bSkip:=false; AddPart(ts,sPart); end; sPart:=sPart+c; end else bSkip:=true; end; AddPart(ts,sPart); while ts.Count<3 do ts.Add('0'); //Ensure 3 date components. end; class procedure TDateUtils.AddPart(var ts:TStringlist; var s:string); {Add a complete component e.g. '7th' to the list.} begin if s<>'' then begin if ts.Count<3 then ts.Add(s); s:=''; //Reset. end; end; It could also handle the 'more than three components present' situation more efficiently.
  12. 🙂 Updating to a different version of Xcode seems to have solved it. Finding a suitable combination of Delphi, PAServer, Xcode, macOS and Fusion versions that will all play nicely together can be tricky.
  13. The IDE copied a PAServer package into the scratch-dir folder for me, which I then installed - so yes it likely is the one from the Delphi program files folder. I'm currently downloading a version of Xcode that I think includes Python 3.8 and still supports Catalina. Thank you for the link - I'll try the package you suggested from the website, as that might be a quick fix - before I resort to trying to update Xcode.
  14. When I try to run (deploy) an FMX macOS app from Alexandria 11.2 I get the following error message: "Unable to start LLDB kernel: 'Symbolic link target does not exist: /Applications/PAServer-22.0.app ... Xcode.app ... Versions/3.8/Python3. Please make sure that the target exists or update the link to point to the new location of the Python 3 installation'. On the Windows side I have Alexandria 11.2 on a Windows 10 VM (VMWare Fusion 11.5.6). On the Mac side I have PAServer22 Version 13.2.11.7 on macOS Catalina 10.15.7 Pretty sure I had this working in an earlier release of Alexandria(?). Everything runs fine with Delphi 10.4.1 and PAServer21 on the same system. I'm guessing I need Python 3, or if that's already present, some way to tell PAServer where Python 3 is located? Edit: A look inside the package contents of Xcode.app reveals Python 3 is located in ... Frameworks/Python3.framework/Versions/3.7/Python3 So 3.7 vs 3.8 - I wonder whether it actually requires 3.8 or whether there's a way to point it to 3.7 ?
  15. Incus J

    Puzzled by StrToDate

    I've created a general purpose string to date function that is quite tolerant and can parse a variety of date strings using just a couple of parameters like this: 'February 7th, ''23', TDateOrder.doMDY Its current tolerance for variations (e.g. 'Feb 7 2023' '02/07/23' "7th.02 '23") risks it getting creative if fed a string that isn't really a date, but I can tighten it up later if it needs to be stricter (famous last words - what could possibly go wrong).
×