Jump to content

A.M. Hoornweg

Members
  • Content Count

    494
  • Joined

  • Last visited

  • Days Won

    9

Posts posted by A.M. Hoornweg


  1. 2 minutes ago, Mike Torrettinni said:

    Yes, I can't imagine how slow it would be on HDD.

    And what you are describing is the reason IDE should be better optimized. Perhaps future versions of LSP will help. It's hard to imagine every installation should tweak all these possible settings to find the right ones for Delphi.

     

    It is one of the reasons why I'm not a friend of "skinning".   

     

    But my changed Windows settings tackle the root cause which is unnecessary re-drawing of UI elements for the sake of smoothness and animations. I don't need any of that. Responsiveness is much more important.


  2. @Mike Torrettinni do you have your virtual machine on a SSD?  You should, it makes a dramatic difference.

     

     

    One more thing about VMWare and GPU acceleration. 

     

    My notebook happens to have more than one GPU.  It has an Intel adapter but also a faster additional NVIDIA GPU.   A nice but little known feature of VMWare is that it lets you select which GPU to use, but tweaking such advanced settings involves manually editing the virtual machine's *.vmx file.  These changes make the virtual machine less "portable" between host machines since different host machines may have different GPU's.   

     

    mks.dx11.vendorID = "0x10de"

    (This selects the NVidia GPU.  "0x8086" selects Intel, "0x1002" selects AMD)

     

    mks.enableDX11Renderer = "TRUE"     

    (This enables DirectX11/OpenGL  acceleration. It is the default setting).
     

    Some DirectX drivers have been "blacklisted" by VMWare for some reason; in that case no DirectX/OpenGL acceleration is available at all inside VM's. This might be an explanation for slow behavior. But luckily you can override even that setting in the *.vmx file:

    mks.gl.allowBlacklistedDrivers = TRUE

     

     

     

    One more thing about VMWare Workstation in general.  Normally if one uses VMWare one would leave Hyper-V disabled on Windows and let VMWare handle all the virtualization.  But the latest VMWare version 15.5.X can also run "on top of" Hyper-V.  I don't know if there's a speed penalty involved with that.  There might be.

     

     

     

     

     

     


  3. In my case, every project is generally in its own repository.

    Some projects, however, consist of many sub-projects (for example, a main project and a bunch of plugins/dlls and maybe a configuration program); in such a case, I keep these in one repository because they count as one big project.

     

    Almost all my projects use a bunch of libraries, some of which are commercial ones. And of course I keep each of these libraries is in a repository of its own. Source code versioning systems like Subversion and Git allow you to reference "external" repositories for libraries (in Git they are called Submodules).   So each of my project repositories has a subfolder "externals" where it automatically downloads the libraries which it needs.  

     

     

     

     

     

     

     

     

     

     

     

     

    • Thanks 1

  4. I just noticed that TMS VCL UIPack  supports drawing SVG graphics and there's even a tAdvSVGImageCollection. I haven't tested it myself though.  I quote from the manual:

     

     

    "SVG supported elements:
    - circle
    - clipPath
    - defs (limited to predefined style, no gradients, no paths, only single fill/stroke parameters)
    - ellipse
    - g
    - image (limited to base64 encoded string value)
    - line
    - path
    - pattern (no gradients, no paths, only single fill/stroke parameters)
    - polygon
    - polyline
    - rect
    - style
    Within the style element supported parameters are:
    - fill (no gradients)
    - stroke (no gradients)
    - stroke-width
    - opacity
    Within the primitives (line, polygon, polyline, rect, path) supported parameters are:
    - fill (no gradients)
    - stroke (no gradients)
    - stroke-width
    - transform (scale, rotate, translate, matrix)
    With SVG support in TMS VCL UI Pack we aim for smaller SVG icon sets that can be used to target
    normal and high DPI applications. When scaling, SVG will scale accordingly and still render sharp at
    different resolutions. SVG support has been added to avoid the need for numerous icons for each
    different scale / resolution"


  5. The problem is caused by the fact that a VM does not have a "real" accelerated graphics adapter. So lots of graphical bells and whistles that are used by Windows 10 (such as "smooth" scrolling, transparency, drop shadows, animations of menus and listboxes etc) are done by the much slower CPU instead of by the GPU. 

     

    And that is VERY noticeable in the Delphi IDE.  Disabling those options in Windows made my Delphi 10.4 FLY instead of crawl.


  6. I have that same setup.

     

    My Delphi 10.4 enterprise IDE was very sluggish until I changed some Windows 10 settings inside the VM as well as on the host machine.  After those changes it behaves much faster. 

     

    -> start - control panel

    -> in the control panel, double-click the "System" applet

    -> click "Advanced system settings"

    -> in the field "Performance", click the button "Settings"

     

    Then select the settings as in the image below.  Re-start windows.

     

     

     

     

     

    speed settings.png

    • Like 1

  7. You could use OutputDebugString in conjunction with Sysinternals' DebugView  to monitor the size of your lists in certain time intervals. 

    That way you can observe if one of your lists is growing out of control.

     

    DebugView can do tcpip client/server by the way, that way you can observe the debugging output on a different computer.


  8. 2 hours ago, Lars Fosdal said:

    We are fighting a memory leak, but neither FastMM nor EurekaLog reports what is leaking.

    This is a service without a GUI, which uses COM objects, sockets and FireDAC databases.

     

    Is there a non-UI FastMMUsageTracker anywhere that could shine light on if this is a fragmentation issue?

    Are there other things that I should be looking at using?

    Maybe you should look at allocations that bypass Delphi's memory manager and hence not get caught by FastMM4. I mean stuff like VirtualAlloc, GlobalAlloc, LocalAlloc and HeapAlloc. Are you using any external DLLs written in C ?.   

     

    You max need a tool like AQTime or Deleaker to track down such leaks.

     


  9. YES you need it. With a  source control system you can make as many backups (commits) per day as you want and you can return to any older version of a file if you broke something.

     

    A few tips:

    - There are very good freeware GUIs available (such as TortoiseSVN and TortoiseGit).  Please use those, they save a lot of hassle.

    - I personally don't let the Delphi IDE manage the files in the repository, I prefer to do it manually.  I use both svn and git, but I use them exclusively using the aforementioned tools.

    - It isn't really necessary to use an external server for your own (non-shared) repositories.  An external USB drive will do just fine.  

    - Whenever you want to add/delete/move/rename a file in your working copy, don't do it with the Windows explorer, only do it with Tortoise. 

    • Like 2
    • Thanks 1

  10. 15 hours ago, pyscripter said:
    • TAggregatedObject simply reflects QueryInterface calls to its controller.  From such an aggregated object, one can  obtain any interface that the controller supports, and  only interfaces that the controller supports.  This is  useful for implementing a controller class that uses one
        or more internal objects to implement the interfaces declared  on the controller class.  Aggregation promotes implementation  sharing across the object hierarchy.
    • TContainedObject is an aggregated object that isolates  QueryInterface on the aggregate from the controller.    TContainedObject will return only interfaces that the  contained object itself implements, not interfaces  that the controller implements.

    Okay, that makes sense; so if I use tAggregatedObject then I can use the "AS" keyword to freely switch between the inner and the outer interface (see example 1) whereas in tContainedObject that isn't possible (it would only let me switch from the outer to the inner interface, right?) .

     

     

     

     

     


  11. On 7/1/2020 at 9:12 AM, Mahdi Safsafi said:

    For curiosity, why are you mixing arabic with latin letters. Does such ArabicLatin word make sense for you? 

    In my experience,  when reporting is done on oil wells in the Middle East, the Arabic text is often interspersed with English technical terms.  And for a developer it is quite a challenge to get mixed  LTR-RTL text input right.   

    • Like 1

  12. 25 minutes ago, Anders Melander said:

    You've answered the question yourself with your example: Use TAggregatedObject when the inner object is reference counted.

    But tAggregatedObject doesn't DO the reference counting, it lets the controller (the owner)  do that.  And the controller explicitly manages the inner object's lifetime, not through reference counting.

    function TAggregatedObject._AddRef: Integer;
    begin
      Result := FController._AddRef;
    end;

    And when using a plain vanilla tObject (my examples 2 and 3), the owner ALSO does the reference counting.  Same thing, but faster (since the _addref isn't chained).     So I still don't see what tAggregatedObject is actually meant for, what problem it is supposed to solve!  

     

     

     


  13. COM is not the problem, I've been implementing COM objects for years. 

     

    My question is really specific about the correct use and usefulness of tAggregatedObject and tContainedObject, because as far as I can see they are not needed at all to build aggregates, tInterfacedobject can already do so using ordinary tObjects.  So I'm probably missing something essential about their use and usefulness!

     

    For example, this aggregate uses a tAggregatedObject:

     

    type
      iHello = interface
        ['{58AD07B9-FCE5-494A-94B2-E1CAF7D05B1D}']
        procedure Hello;
      end;
    
      iGoodbye = interface
        ['{35079C32-AF3D-4E9D-808C-6A6DDED38663}']
        procedure Goodbye;
      end;
    
      tAggregate = class(taggregatedobject, iHello)
        procedure Hello;
      end;
    
      tCompositeObject1 = class(tinterfacedobject, iHello, iGoodbye)
      protected
        ainner: tAggregate;
        function GetInner: iHello;
      public
        procedure Goodbye;
        destructor Destroy; override;
        property Inner: iHello read GetInner implements iHello;
      end;
    
    procedure tAggregate.Hello;
    begin
      messagebox(0, pchar('Hello'), pchar('Hello'), mb_ok);
    end;
    
    
    destructor tCompositeObject1.Destroy;
    begin
      messagebox(0, pchar('Destructor'), pchar('tCompositeObject1'), mb_ok);
      ainner.free;
      inherited;
    end;
    
    function tCompositeObject1.GetInner: iHello;
    begin
      if not assigned(ainner) then
        ainner := tAggregate.create(self);
      result := ainner;
    end;
    
    procedure tCompositeObject1.Goodbye;
    begin
      messagebox(0, pchar('Goodbye'), pchar('Goodbye'), mb_ok);
    end;
    
    
    procedure TestCode1;
    var
      Hello: iHello;
      Goodbye: iGoodbye;
    begin
      Goodbye := tCompositeObject1.create;
      Goodbye.Goodbye;
      Hello := Goodbye as iHello;
      Hello.Hello;
    end;

     

    ... and this one does the very same thing using a plain vanilla tObject:

     

    type
      iHello = interface
        ['{58AD07B9-FCE5-494A-94B2-E1CAF7D05B1D}']
        procedure Hello;
      end;
    
      iGoodbye = interface
        ['{35079C32-AF3D-4E9D-808C-6A6DDED38663}']
        procedure Goodbye;
      end;
    
      tSimpleObject = class
        procedure Hello;
      end;
    
      tCompositeObject2 = class(tinterfacedobject, iHello, iGoodbye)
      protected
        ainner: tSimpleObject;
        function GetInner: tSimpleObject;
      public
        procedure Goodbye;
        destructor Destroy; override;
        property Inner: tSimpleObject read GetInner implements iHello;
      end;
    
    procedure tSimpleObject.Hello;
    begin
      messagebox(0, pchar('Hello'), pchar('Hello'), mb_ok);
    end;
    
    
    destructor tCompositeObject2.Destroy;
    begin
      messagebox(0, pchar('Destructor'), pchar('tCompositeObject2'), mb_ok);
      ainner.free;
      inherited;
    end;
    
    function tCompositeObject2.GetInner: tSimpleObject;
    begin
      if not assigned(ainner) then
        ainner := tSimpleObject.create;
      result := ainner;
    end;
    
    procedure tCompositeObject2.Goodbye;
    begin
      messagebox(0, pchar('Goodbye'), pchar('Goodbye'), mb_ok);
    end;
    
    
    procedure TestCode2;
    var
      Hello: iHello;
      Goodbye: iGoodbye;
    begin
      Hello := tCompositeObject2.create;
      Hello.Hello;
      Goodbye := Hello as iGoodbye;
      Goodbye.Goodbye;
    end

     

    So is there any advantage in using tAggregatedObject / tcontainedobject  at all ?

     

     

    I currently see more advantages in using tObject, because that allows me to take an existing class and encapsulate it inside a wrapper class whenever I want it to be interface based.  For example, these few lines of code make a tStringlist interface-based, expose the methods add, get and put and make the whole thing reference counted:

     

    type
      // Just expose a selected bunch of methods of tStrings
      iStrings = interface
        ['{242798EB-0A53-4284-BA16-306FF354E2AC}']
        function Add(const S: string): Integer;
        function Get(Index: Integer): string;
        procedure Put(Index: Integer; const S: string);
        property Strings[index: Integer]: string read Get write Put; default;
      end;
    
      tInterfacedStrings = class(tinterfacedobject, iStrings)
      protected
        fList: tStringlist;
        function getList: tStringlist;
      public
        destructor Destroy; override;
        property list: tStringlist read getList implements iStrings;
      end;
    
    
    destructor tInterfacedStrings.Destroy;
    begin
      fList.free;
      inherited;
    end;
    
    function tInterfacedStrings.getList: tStringlist;
    begin
      if not assigned(fList) then
        fList := tStringlist.create;
      result := fList;
    end;

     

     

     


  14. Hello all,

     

    does anyone have any links to documentation/examples about the correct use of tContainedObject and tAggregatedObject? 

    I find the little documentation I can find rather confusing.

     

    Kind regards,

    Arthur

     


  15. On 6/30/2020 at 1:00 PM, Dave Nottage said:

     Tools|Options, Deployment > SDK Manager:

     

    It wouldn't work. I have de-installed Delphi Sydney and deleted all Embarcadero folders and registry keys plus everything that had to do with Java and Android.

    Then I re-installed Delphi and now the compiler deploys the executable as expected. 

     

    The executable won't start on Bluestacks 4 (screen stays black), however, so I'll try a hardware device next.

     

     

     


  16. 4 hours ago, Dave Nottage said:

    Sorry, I had it confused with another issue. I just had exactly the same issue as you (on a machine I don't use often), and solved it by changing the SDK settings to use build-tools\29.0.3 (instead of 28.0.3) for ZipAlign.exe and AAPT.exe

    I would be totally grateful if you'd tell me how to do that! I'm an absolute beginner with Android.


  17. 2 hours ago, Dave Nottage said:

    The problem you're seeing is usually due to an outdated AndroidManifest.template.xml file. Deleting the file (a new one will be recreated) should resolve the issue

    Deleting the xml file makes no difference. It gets re-created, yes, and then I get the exact same error messages as before.   And then Delphi hangs completely, I have to shoot it down in the task manager.  All in all, deploying to Android seems unfunctional.


  18. Hello all,

     

    I'm totally new to Android, and so far I'm having zero success getting Embarcadero's sample programs to run on Android.

     

    I am running Delphi 10.4 inside a VMWare VM.  On my host machine, I have the Bluestacks 4.215.0.1019 emulator running, with ADB debugging enabled. 

     

    Connection details: I am aware that Bluestacks only binds to localhost (127.0.0.1) so I have setup a port forwarding on the host (netsh interface portproxy add  v4tov4 listenport=5556 connectaddress=127.0.0.1 connectport=5555) so that I can connect to the emulator from external IP addresses through TCP port 5556. I have enabled both ports 5555 and 5556 in the firewall.  I have tested this setup and I can successfully connect to the emulator from my Delphi VM ("adb connect ip-address:5556") and send adb commands to it.  I had expected this connectivity to be the biggest hurdle but it worked immediately.

     

     

    I have cloned Embarcadero's official sample repository from github (https://github.com/Embarcadero/RADStudio10.4Demos.git) and now I'm trying to compile and run the application in "Samples\Object Pascal\Multi-Device Samples\User Interface\Forms".  I've activated the Android 32-bit target (guessing that Bluestacks emulates a 32 bit device) and the Delphi IDE "sees" the device without problems (see screenshot),  it's called "SM-G973F".  

     

     

    Since this is an "official" demo application, I was hoping things would work out of the box so I could use it as a starting point! 
    But when I press F9, Delphi does a lengthy compiling act, and then throws the following errors:


     

    [PAClient Error] Error: E2312 Unable to execute '"C:\Users\Public\Documents\Embarcadero\Studio\21.0\PlatformSDKs\android-sdk-windows\build-tools\28.0.2\Aapt.exe" 
    package -f -M "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\AndroidManifest.xml" 
    -F "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\bin\Forms-unsigned.apk" 
    -I "C:\Users\Public\Documents\Embarcadero\Studio\21.0\PlatformSDKs\android-sdk-windows\platforms\android-26\android.jar" 
    -S "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\res" 
    -A "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\assets" 
    "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\library" 
    "C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\classes"' 
    (Error 1)
    
    
    [PAClient Error] Error: E2312 
    C:\Users\Public\Documents\Embarcadero\Studio\21.0\Samples\Object Pascal\Multi-Device Samples\User Interface\Forms\Android\Debug\Forms\AndroidManifest.xml:21: 
    error: No resource identifier found for attribute 'requestLegacyExternalStorage' in package 'android'

     

    The error messages aren't helpful at all, what the heck is "Error 1" supposed to mean?   Can anyone point me to a solution?

     

    Thanks in advance,

    Arthur

     

     

     

     

    Delphi.png

×