Jump to content

A.M. Hoornweg

Members
  • Content Count

    447
  • Joined

  • Last visited

  • Days Won

    8

Posts posted by A.M. Hoornweg


  1. 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.


  2. 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


  3. Hello all,

     

    when I deploy a FMX application to Ubuntu (in this case the "Screenshot" fmx demo) the Delphi 10.4 debugger hangs totally.  My Windows and Linux machines are both VMWare VM's.

     

    I can see that the freshly compiled executable appears in the home/PAServer/scratch-dir/myname/Screenshot directory. The message log in the Delphi IDE gives a warning "Local file \Redist\libfmux.so not found. Skipping deployment."

     

    The executable is not started on the Linux system by PAServer.  I am able to start the executable manually, so the executable itself must be OK. 
    But Delphi hangs so thoroughly that I can't debug it. I can only terminate Delphi in the task manager.  

     

    Am I doing something wrong?

     

     

     


  4. Hello all,

     

    does anyone know if Delphi 10.4 can co-exist peacefully with 10.3 Rio on the same system without one breaking the other, and can I un-install Rio later without damaging the Sydney installation? Especially if one intends to do some multi-platform (Android/Linux) work?


  5. On 4/17/2020 at 10:39 PM, Anders Melander said:

    While Application.ProcessMessages is evil it isn't the cause of the problem here.

     

    Use PostMessage instead of SendMessage. SendMessage calls the message handler directly and doesn't use the message queue at all.

    https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage

     

    I wonder about sendmessage being executed in the context of the calling thread.  Is that documented somewhere?  The HWnd could be in an entirely different process, so there must be some kind of marshaling in between. 

     

     

     

     

     

     


  6. I use interfaces all the time, and there are simple ways to make existing classes support interfaces with or without reference counting, without having to derive from a common base class like tInterfacedObject.

     

     

    If I want to modify any class in such a way that it supports interfaces without reference counting, I simply add dummy methods _AddRef, _Release, and QueryInterface:

     

    Type
    tNewObject = class(TOldObject, IInterface)
      protected
        // IInterface
        function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
      end;
    
    function tNewObject._AddRef: Integer;
    begin
      Result := -1;
    end;
    
    function tNewObject._Release: Integer;
    begin
      Result := -1;
    end;
    
    function tNewObject.QueryInterface(const IID: TGUID; out Obj): HResult;
    begin
      if GetInterface(IID, Obj) then
        Result := S_OK
      else
        Result := E_NOINTERFACE;
    end;

     

    And similarly, it is possible to make any existing class support interfaces with reference counting, it just takes a few more methods: 

     

    
    TNewObject = class(TOldObject, IInterface)
      protected
        FRefCount: Integer;
        function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
      public
        procedure AfterConstruction; override;
        procedure BeforeDestruction; override;
        class function NewInstance: TObject; override;
        property RefCount: Integer read FRefCount;
      end;
    
    procedure TNewObject.AfterConstruction;
    begin
    // Release the constructor's implicit refcount
      InterlockedDecrement(FRefCount);
      Inherited;
    end;
    
    procedure TNewObject.BeforeDestruction;
    begin
      if RefCount <> 0 then
        Error(reInvalidPtr);
      Inherited;
    end;
    
    // Set an implicit refcount so that refcounting
    // during construction won't destroy the object.
    
    class function TNewObject.NewInstance: TObject;
    begin
      Result := inherited NewInstance;
      TNewObject(Result).FRefCount := 1;
    end;
    
    function TNewObject.QueryInterface(const IID: TGUID; out Obj): HResult;
    begin
      if GetInterface(IID, Obj) then
        Result := 0
      else
        Result := E_NOINTERFACE;
    end;
    
    function TNewObject._AddRef: Integer;
    begin
      Result := InterlockedIncrement(FRefCount);
    end;
    
    function TNewObject._Release: Integer;
    begin
      Result := InterlockedDecrement(FRefCount);
      if Result = 0 then
        Destroy;
    end;

     

    • Like 2

  7. 4 hours ago, dummzeuch said:

    That's actually one change I made over Easter: The Formatter does no longer insert a blank line between a comment and the procedure it describes.

     

    Are there any other experts in GExperts that do this?

    I don't know. But I wouldn't rely on the absence of blank lines because there are several other code formatters around.

     

    For example, I need to maintain some source code that must remain compatible with Delphi XE.  The built-in source code formatter of XE doesn't know how to format anonymous methods properly, so I use CNPack's formatter there.


  8. Lately I've been switching to this style:

    Function tMyClass.GetCustomerName(CustomerID:tGuid; OUT CustomerName:String):Integer;
    {Retrieves the name of a customer. Exceptions:None; 
    Result<>0 means error. See table ### for a list of possible errors}
    Begin
       Result:=0;
      Try
       ....   read customer name    
      Except
        Result:=DetailedError;
      End;
    End;

     

    My reason for putting the comment inside the method is that the comments will fold out of view along with the method body when I use the folding feature of the IDE.  If I want to know what a method does exactly, I simply unfold that single method and the first thing I see is the comments. This way I can have the documentation where I prefer to have it (near the code) and keep it out of view most of the time.  I chose a light gray font for the comments to make them as un-obtrusive as possible.

     

    An additional advantage of having the comments inside the method body is that it prevents tools such as MMX, Cnpack, GExperts etc from inadvertently separating the comment from the method it belongs to.  

     

     


  9. 3 hours ago, Dany Marmur said:

    on mobile so not verbose:

    it was the painting of the IDE, win10 berlin dx ribbon = sluggish esp if the dwm gets qirky.

    A lot can be accelerated by changing some Windows 10 settings inside the VM:

     

    Control panel ->

    System ->

    Advanced system settings ->

    Advanced ->

    Performance settings ->

    Adjust for best performance.

     

    Then re-enable only the absolute minimum ("show window contents while dragging" +  "smooth edges of screen fonts")

     

     

     

     


  10. On 3/27/2020 at 7:02 PM, Remy Lebeau said:

    Then don't do such things on strings/interfaces containing sensitive data.  And do use things like the CryptProtectMemory(), CryptUnprotectData(), and SecureZeroMemory() functions to secure the sensitive data in memory while you are not actively using it.

    My application needs to call sp_setapprole on MS SQL Server which requires a user name and password.  So for a brief time I need these in cleartext form. 

     

    They are currently stored in an AES encrypted file and I decrypt them on the fly when I need them, using Turbopower Lockbox 2.09.  I have no way of knowing if its decryption engine leaves any decoded text in freed blocks on the heap so I thought it would be great if I could simply instruct the heap manager to wipe whatever memory is released. This would prevent the password from appearing in a memory dump.

     

    Edit: The actual SQL Query is executed using

    connection.execute(format('exec sp_setapprole ''%s'', {Encrypt N ''%s''}, ''odbc''', [Approle, Approlepassword]));

    so I cannot exclude the possibility that the "execute" and the "format" commands might put temporary stuff on the heap as well.

     

     

    [edit] the GitHub feature request you mentioned was mine...


  11. Hello all,

     

    I'd like to know if it is possible to activate the FastMM4 Option "AlwaysClearFreedMemory" temporarily/on demand in code? 

    The reason being that some of my routines work with confidential passwords/hashes.  Delphi often uses temporary "hidden" strings and interfaces (for example when concatenating strings) so there's the risk of legible stuff remaining in RAM when such a routine exits.  


  12. 2 hours ago, eivindbakkestuen said:

    You may want to test docking. You're not locked to docking the windows in particular places, they can float around on the "desktop" inside your application. You decide what kind of docking etc operations are applicable (perhaps you have a few child windows where it would be appropriate to only see one of them at a time, so would work in a tabbed child window, etc). I'm attaching an image of an application using the DevEx docking library; could just as well have been done with MDI.

     

    image.thumb.png.f998ec7eeee23cdeea3fd1f04fa612cb.png

    This looks promising.

     

    My current situation looks very much like this.  Users have many views and editors open simultaneously and entering data in one view can change the graphic output in another view:

     

     

     

     

    2020-03-27 14_46_45-.png


  13. 14 hours ago, Vincent Parrett said:

    @A.M. Hoornweg have a look at the LMD Docking library, we use it in FinalBuilder and it is by far the best implementation of docking I have seen for delphi.  

     

    https://lmd.de/products/vcl/lmddockpack/

     

    You can save layouts and switch between them quite easily. In FinalBuilder, we save the layout separately for when there is 1) no projects open, 2) projects open in design mode and 3) when a project is running. Switching layouts is pretty simple and saving/restoring them them is trivial.   

    Hmmm. I have a subscription to both LMD VCL Complete and Finalbuilder.


    Though I love Finalbuilder, the docking solution it uses is unsuitable for my own application. Finalbuilder is basically an IDE, I love it, but the actual fiddling with action properties is done with modal dialog windows son one can only fiddle with one thing simultaneously.

    And re-arranging docked panels is by no means trivial. You see, once you detach a panel it has to fit into a rectangular space somewhere. You can't just place the panel anywhere you like, it's not like other panels will intelligently move out of the way if you want to drop one somewhere.  When I try, I find myself dragging a panel around, hoping it will snap in somewhere suitable.  So once I have a usable layout, I simply try not to break it!

     

     

    MDI may not be the prettiest solution but it actually solves a ton of problems. Open a dozen views or editors at once? Check. Auto-align them all? Check.  Want to maximize one of them? It takes just one click. Restore the previous situation? One click.  

     

     

     

    • Like 1

  14. Just now, Anders Melander said:

    Sounds like docking is the better choice then.

    "Docking" is a paradigm that lets the users assemble a view layout that is not supposed to change often (because docking is awkward).   

     

    In my case that won't work.  There are over 50 scalable views in my application and the user needs most of them on a daily basis.   And often there will be multiple instances of the same view type open,  to compare data from the oil well with older reference wells nearby.


  15. 1 minute ago, Lars Fosdal said:

    It would actually be nice to have something MDI like - but without the container.
    It would need multi-display support.  The main window could be a narrow up top thing, or a sidebar thing.
     

    That's the second mode in which my application works. A toolbar at the top and free floating windows that can be moved between screens.   Only... The users don't want to use it that way.


  16. 2 minutes ago, Anders Melander said:

    Anyhoo, to actually address then issue, if the OP wants to maintain MDI and support High-DPI then I would recommend having a look at DevExpress' Tabbed MDI:

    https://community.devexpress.com/blogs/thinking/archive/2010/08/16/vcl-tabbed-mdi-multiple-document-interface.aspx

     

    Another alternative is to use docking. Just don't use the VCL docking. It sucks.

    "Tabbed MDI" hides views from sight.

     

    In my application, editing data in one view influences calculated values and graphical output in other views and the user really needs to have these views in sight simultaneously.  That's the whole point, to have multiple views in sight and to let the user rather than the GUI paradigm decide which ones he wants to see.


  17. The whole thing with MDI is that it is not only suitable to offer a user multiple documents at the same time, but also multiple views at the same time.  I haven't seen a good GUI alternative for that. 

     

    Anything with tabs, bars, pagecontrols etc basically serves to only hide views from sight which is quite the opposite of what I need.  

    • Like 1

  18. 43 minutes ago, Lars Fosdal said:

    The last time I checked, I got transparent client areas and border areas.

    I've never noticed. All my mdi client forms have either a panel or a tscrollbox in the background.


  19. 1 hour ago, Lars Fosdal said:

    MDI has been deprecated for years and is severely broken under Windows 10.  Seems that a lot of messages no longer are sent or passed down to children.

    MDI itself works fine on Windows 10 for me. 

×