Jump to content

Anders Melander

Members
  • Content Count

    2854
  • Joined

  • Last visited

  • Days Won

    156

Posts posted by Anders Melander


  1. 37 minutes ago, David Schwartz said:

    The last time I looked at any code required to program a Windows Message Loop was maybe 1993 ... I might have spent one day messing with it and just wanted to throw up.

    Huh?

    var Msg: TMsg;
    while (PeekMessage(Msg, 0, WM_SETCURSOR, WM_SETCURSOR, PM_REMOVE)) do
    begin
      if (Msg.message = WM_QUIT) then
      begin
        PostQuitMessage(Msg.wParam);
        exit;
      end;
    
      DispatchMessage(Msg);
    end;

     

    • Like 1

  2. 1 hour ago, ventiseis said:

    Is that misleading?

    No. Why would you think that it was?

     

    My own experience is that only having the necessary units in the interface section improves compile time and reduces memory usage during compile.

    It also helps with identifying and minimizing dependencies as I become conscious of them when a unit has to be moved to the interface section.


  3. 2 hours ago, Vandrovnik said:

    I did not make speed tests, the speed will probably be almost the same, because of large file cache and fast NVME drives.

    Exactly. Let the OS manage the RAM; It knows where it's needed the most.

    There are some cases where a RAM disk makes sense but output from a compiler ain't it.

     

    1 hour ago, DelphiUdIT said:

    TLDR; but I wouldn't trust a RAM manufacturer to be unbiased in this matter.


  4. 3 minutes ago, ventiseis said:

    This would support your statement. But this behaviour is broken in our environment: if I compile the same project twice, every single unit is compiled again to dcu - even if I do not change a single line of code!

    It sounds like you should focus on fixing your build environment first 🙂

     

    4 minutes ago, ventiseis said:

    We use an alternative dcu output path in the project options. It is a virtual drive created by the subst utility. If I remove that virtual drive and set the dcu output path to a different path, the documented behavior works again - i have no explanation for this. 

    Well, there you have it. subst is a leftover from DOS and should be avoided.

     

    A file in a virtual (subst) location has (at least) two paths: The virtual path and the physical path. Depending on what windows API a virtual filename is passed though you can either get a result that is relative to the virtual location or to the physical location. I can't give you a concrete example but I've seen it happen many times.

     

    For example, I would guess that if you resolve a virtual filename to a PIDL and then convert that back to a path, then you will end up with the physical path.


  5. Just now, Rollo62 said:

    Maybe a solution would be, to manually verify and correct the EXIF data based on the real orientation data of the phone

    Where do you think the EXIF orientation data comes from? It comes from the camera orientation sensor.

    The problem here is to handle the EXIF data in an existing image.

     


  6. Definitely. I'm not denying that it's a problem. I'm just saying that the problem isn't that it doesn't rotate automatically (because that would also be a problem). The problem is that it doesn't give us any way of knowing that the image needs to be rotated be display.

    You should probably report it as a bug against FMX.

    • Like 1

  7. 22 hours ago, Alexander Halser said:

    That's obvious for everyone who looks at the picture, except for Delphi Firemonkey. TBitmap.LoadfromFile() ignores the EXIF orientation altogether and loads the JPEG with its physical dimensions (which are width 4032 and height 2268 pixels). It doesn't rotate the picture after loading.

    FWIW, TBitmap/TJPEGImage are low-level image containers. It's not their job to rotate or mirror the image because they don't know what you want to do with the image after load.

     

    So, if anything, the problem is that the classes don't surface the EXIF information so you can apply the transformation after load if you want to.

    • Like 1

  8. 4 hours ago, Anders Melander said:

    the code it will probably be public later tonight

    The API: https://bitbucket.org/anders_melander/better-translation-manager/src/master/Source/amDialog.Manager.API.pas

    The implementation: https://bitbucket.org/anders_melander/better-translation-manager/src/master/Source/amDialog.Manager.pas

     

    And here's the commit that introduced it: https://bitbucket.org/anders_melander/better-translation-manager/commits/c1341cb4eaaab433ee1680fcbd22e5dc570a5b97

    It contains a few examples of changing some modal dialogs from traditional Create/Free to interfaces & DialogManager.CreateDialog.

     

    As usual, sorry about bitbucket 😕

    • Thanks 1

  9. 1 hour ago, araujoarthur said:

    Is it possible to make IncludeDialog, WarnDialog and ErrorDialog available upon uses of Forms.Dialog?

    Not directly; Delphi unfortunately doesn't support "wildcard" includes like that.

     

    The way I do it, for something like dialogs, is to associate each dialog with an interface and then separate the implementation of the dialog from the interface:

    unit Foo.Dialogs.Bar.API;
    
    type
      IFooDialogBar = interface
        ['{4279694B-C3D6-4B2A-A134-CEACDF6185AF}']
        function Execute: boolean;
      end;
    unit Foo.Dialogs.Bar;
    
    interface
    
    uses
      Forms,
      Foo.Dialogs.Bar.API;
    
    type
      TFormFooBar = class(TForm, IFooDialogBar)
        // ...other stuff here...
      private
        // IFooDialogBar
        function Execute: boolean;
      end;
    
    implementation
    
    function TFormFooBar.Execute: boolean;
    begin
      Result := (ShowModal = mrOK);
    end;

     

    In order to create the dialog you could use a factory function like Peter suggested:

    function FooDialogBar: IFooDialogBar;
    begin
      Result := TFormFooBar.Create(nil);
    end;

    You will then have to manage the lifetime of the dialog somehow. Since you are accessing the dialog object via an interface you can't just free it once you are done with it. It will have to be done via reference counting.

    Unfortunately the default TComponent reference counting will not do it so it will have to be modified (overridden).

     

    I have a dialog manager that takes care of all this without the need to modify anything. It handles both modal and non-modal dialogs. I'm in the process of adding it to the translation manager project, so the code it will probably be public later tonight or tomorrow.

     

    The dialog manager is used like this:

    // Register the dialog API in the initialization section of the disloag unit
    initialization
      DialogManager.RegisterDialogClass(IFooDialogBar, TFormFooBar);
    end;
    ...
      // Create dialog
      var DialogBar := DialogManager.CreateDialog(IFooDialogBar) as IFooDialogBar;
    
      // Display dialog
      if (DialogBar.Execute) then
      begin
        ...
      end;
      
      // Lifetime is controlled via reference counting.
      // When interface goes out of scope, the dialog object is destroyed.
    ...

     

    • Thanks 1

  10. 22 minutes ago, phqsoft said:

    would you mind to help me to make the display text in DisplayBanner to white instead of black?

    In TFormSplash.UpdateBannerImage:

          if (Scale = 255) then
            PixDst^ := PixSrc^
          else
          if (Scale = 0) then
            PixDst^ := PixSrc^ or $00FFFFFF // *** Change this ***
          else
          begin
            RGB := PixSrc^ and $00FFFFFF;
            RGB := RGB xor $00FFFFFF; // *** Add this ***
            PixDst^ := (PixSrc^ and $FF000000) or
              (Div255((RGB shr 16) * Scale) shl 16) or
              (Div255((RGB shr 8 and $FF) * Scale) shl 8) or
              (Div255((RGB and $FF) * Scale));
            PixDst^ := PixDst^ xor $00FFFFFF; // *** Add this ***
          end;

    This isn't the most elegant solution but since the original code was a bit of a hack (which is also why the solution isn't obvious at all) I guess it doesn't matter.

     

    Anyway, what it does is invert the color of the source pixel, blend it with the (black) text, and then invert the result again.


  11. Just now, Lajos Juhász said:

    Instead of running away from this terrible problem. Anders you should write a class helper to help to solve this gigantic bug in the design. I mean how can we live and use Delphi knowing that it has this very poorly design in the fundamental part of the VCL.

    I dunno. I think it's pointless. I mean, properties? Pfft! What's the point?

    Delphi is dead anyway and if there's one thing the past 30 years has shown it is that the design is flawed beyond repair but we were just too ignorant to notice. If only we had been told about this before. The shame is unbearable.

    • Haha 1

  12. 26 minutes ago, dormky said:

    Heavy disagree. A message/event driven environment should, you know, actually use events instead of mixing in state monitoring.

    If you use ShowModal then you are using the modal loop built into the VCL which relies on exiting the loop when ModalResult<>mrNone.

     

    If you disagree with that design then don't use ShowModal; Use Show and build your own modal handling around it. And good luck doing that without a loop which monitors some kind of state flag.

     

    I don't think you have thought this through.

    • Like 1

  13. 17 minutes ago, David Schwartz said:

    Actually, it turns out he's a contractor and I think they "parked" him on this project until his contract runs out.

    That makes better sense because there was something really fishy about the prerequisites of that project.

     

    I once designed, on paper, a large enterprise support system in which one of the key components was a telekinetic interface. The goal of the design was to get fired (long story).
    It sounds as if these people used the same strategy.


  14. 1 hour ago, PeaShooter_OMO said:

    You most probably have an advantage to those starting their programming career on multi-core, mega-memory, full fledged operating system computers; you are conscious about space and performance.

    I agree. One of the things that have helped me tremendously over the years as a software developer is my (hobby) background in first analog electronics and then digital, hardware and then software. It gives one a deep understanding of how things work and why.
    There was also an early phase where I ventured into chemistry but, although I got really good at blowing shit up, I don't think that particular skill set has helped me much 🙂

     

    (and thanks 😘 )

    • Like 2

  15. 1 minute ago, ErikT said:

    it isn't obvious to me which TComponent would be the owner.

    You don't need an owner; Just specify nil as the owner in the constructor and remember that you have to destroy the object in the thread destructor (or on exiting Execute, if you create it there).

     

    Generally, the purpose of Owner is to have a TComponent destroyed automatically when the owner is destroyed, which is handy when you place stuff on a form. For dynamically created components it is better to control the lifetime (Create/Destroy) explicitly so you have complete control of what is going on and when. It also makes the code easier to understand when you don't rely on implicit behavior.

    • Like 1

  16. 22 minutes ago, ErikT said:

    makes the link between the OnReceiveData event and my method?

    Yes.

     

    22 minutes ago, ErikT said:

    should never have been there in the first place?

    It doesn't hurt but if you are not referencing the type then you might as well delete it.

     

    10 minutes ago, PeaShooter_OMO said:

    you need to be certain that the ComPortDriver does not do thread-UNsafe things. 

    I couldn't spot any obvious issues after a brief look through the source.

     

    One thing I would do though, is to move the TCommPortDriver.Create into the Execute method so it is constructed in the context of the thread, instead of the calling thread (which is supposedly the main thread).

    • Like 1
×