Jump to content

aehimself

Members
  • Content Count

    1089
  • Joined

  • Last visited

  • Days Won

    23

Posts posted by aehimself


  1. 3 hours ago, Darian Miller said:

    Copy the EnvOptions.proj file to the APPDATA folder of the user account which will execute the builds

    As an alternate, the path where this file is attempted to be loaed from can be changed in Program Files\Embarcadero\Studio\xx\bin\Codegear.Common.Targets inside the PropertyGroup tag. This is what we ended up using on Azure DevOps at work:

    image.thumb.png.acd9184921f116939d278d43e07c14c5.png

     

    Be careful, though. Changing these to a static path will result all users on the same machine to use the very same environment.proj and/or envoptions.proj. This might be, or might not be wanted.

    • Like 1

  2. Importing an other 3rd party library seems to be a huge overkill just to use a simple mutex.

     

    I have the following code in my .dpr file before any form creations:

      handle := CreateMutex(nil, True, 'MyAppName');
      Try
        If (handle = 0) Or (GetLastError = ERROR_ALREADY_EXISTS) Then
        Begin
          // TMessageDialog.ShowDialog('Only one instance can be running at a time!', dtError);
          handle := FindWindow('TMyApplicationMainForm', nil);
          If IsWindow(handle) Then
          Begin
            ShowWindow(handle, SW_RESTORE And SW_SHOW);
            SetForegroundWindow(handle);
            SetFocus(handle);
          End;
    
          Exit;
        End;
        
        // Form creations, initialization, run here originally from .dpr
      Finally
        CloseHandle(handle);
      End;

    Works like a charm, and you only need WinApi.Windows.
     


  3. On 11/13/2023 at 12:58 PM, PeterPanettone said:

    One thing that has been annoying me for a long time: If you double-click a .DPR file in the File Explorer, it is loaded in the IDE, but the IDE is not brought to the foreground!

     

    Can anyone confirm this - and is there a way to fix this problem?

    This bothered me for ages and never could figure out when it opens in the background and when it opens "correctly".

    What is even more strange I forgot about this behavior when I wrote my BDSLauncher... anyway, now it will attempt to bring the selected instance to the foreground after the file has been opened.

     

    Thank you for reminding!


  4. On 10/31/2023 at 1:52 PM, Anders Melander said:

    For RDP there is an ActiveX but I don't know what it does. I've never used it.
    https://learn.microsoft.com/en-us/windows/win32/termserv/remote-desktop-activex-control

    It indeed exists, and works as advertised. I grabbed installation instructions from somewhere a long time ago:

     

    - Component -> Import Component -> Import ActiveX Control -> Select Terminal Services (mstscax.dll)
    - Palette page: MsTSC, unit dir name: Delphi Lib folder, Search path: empty. Check Generate component wrappers
    - Install to New package
    - Enter the same name (MsTSCLib_TLB.dproj) under Delphi Lib folder
    - Try to build package just to fail
    - Change Property type of ConnectWithEndpoint to "OleVariant", build package again
    - Right-click on MsTSCLib_TLB.bpl in Project manager and select "Install"

     

    After this different versions of the control will appear on the palette and everything can be set (RD gateway, compression, audio redirection, key capture, etc.) via properties what mstsc.exe allows.

    Kinda handy stuff.


  5. I'm using the following code in my custom DBGrid-descendant to have a separate popup menu for the content and the header, which works well. I suppose with little to no modification it can be applied to a TStringGrid too:

     

    Procedure TDBGrid.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    Var
      gc: TGridCoord;
    Begin
      If Button = mbRight Then
      Begin
        gc := Self.MouseCoord(X, Y);
        If gc.Y > 0 Then
          _gridpopup.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y)
        Else If gc.Y = 0 Then
        Begin
          _colindex := gc.X;
    
          If dgIndicator In Self.Options Then
            Dec(_colindex);
    
          _headerpopup.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y);
        End;
      End
      Else
        inherited;
    End;


    _gridpopup is the content popup menu, _headerpopup is the popup menu for the header, _colindex is an integer which can be used later on to determine which column the popup menu was popped up from.


  6. 7 hours ago, gioma said:

    VS2019 is obsolete, you can easily switch to VS2022 (I have converted all my projects without any major problems), but in any case I have never had any problems loading projects.

    The VS2022 you mean which ate up all 16 gigs of memory just when loading the project on all of the developer PCs, finally crashing the OS itself? Not sure if it got fixed since then, but the same project works just fine in 2019; this is why we are not switching. And btw, VS2019 still receives patches.

     

    We are all biased, we all have a preference towards one IDE or an other. The important thing is to stay objective even when we get frustrated.


  7. 4 hours ago, gioma said:

    As mentioned above, time is money and restarting the IDE 5/6 times a day is an unthinkable waste of time!😥

     

    Even at work, where we have DevExpress and a number of other, chunky components installed the IDE loads our big legacy project up in less than 20 seconds. Add 10-15 more seconds of compiling and I am in debugging.

    Compare that with VS2019, which needs ~1min until IntelliSense kicks in, 1,5 min of compiling, 10 seconds of after-compilation-thinking and finally the project launches.

     

    I'm sure there are faster IDEs out there, but Delphi really isn't that bad from startup perspective.

    • Like 9

  8. My advise would be to branch your master and do the conversion there. That way you can cherry pick bugfix commits between them but they would be separated enough.

     

    When conversion is done simply merge/cherry pick everything back to master.

     

    If you have no version control (which you definitely should) you can start to use IFDEFs to separate code. This will make it less readable and does not allow .dfm changes though.

    • Like 2

  9. 1 hour ago, toms said:

    Just open the project in the newer version and see if it compiles, and try to fix the obvious bugs? (This doesn't mean you have to test all the functions to see if anything is broken)

    This was the exact approach I took to convert our legacy application to 64-bit. Our custom component package took about 2 days (plus 2 to fix issues which weren’t obvious), the program itself (1,5M loc) was only one day (plus 7 for fixing the same).

     

    I’m not saying it’s the most sophisticated method but it’s one of the easiest and definitely viable.

    • Like 1

  10. I met that site a couple of times but it never managed to gain my trust for the exact reason you mentioned - a compiled DLL is an extremely unusual way to distribute your code and can do things in the background what you don’t want.

     

    “Don’t fix something which ain’t broke” applies here as well. Don’t purchase something and start to adapt all your code for it if they are working without issues.

    • Thanks 1

  11. On 10/5/2023 at 1:36 AM, azrael_11 said:

    The main reason to seek which Delphi IDE have the "control" to open files is not the double clicking. Is that when i am inside the project i made when i open a form then i get the class name and make with a key compination like ctrl+F1 to open the .pas file of the form.

    But when i have two Delphi IDEs open i cant sent it to open in the specific IDE to open instead that it opens in the last instance of Delphi IDE.

     

    Is there anyway to open this file at runtime from the specific Delphi IDE that i want and not the last one that opens?

     

    Thank you.

    You can discover installed Delphi versions, list their running instances (or start a new one) and instruct them to open a file via TAEDelphiVersions. This is exactly what my configurable BDSLauncher is based on, maybe that one will fit your needs without any extra coding.


  12. By locking you mean they cannot be interacted with?

    If yes, just write a recursive method to walk through your form, disabling / enabling your controls in the process:

     

    Procedure TForm3.LockControls(Const inLockControls: Boolean; inParent: TWinControl = nil);
    Var
      a: Integer;
    Begin
      If Not Assigned(inParent) Then
        inParent := Self;
    
      For a := 0 To inParent.ControlCount - 1 Do
      Begin
        inParent.Controls[a].Enabled := Not inLockControls;
    
        If inParent.Controls[a] Is TWinControl Then
          LockControls(inLockControls, inParent.Controls[a] As TWinControl);
      End;
    End;


     


  13. A little too late, but TSplitView shipped with D11 can also do this, with an addition of animated opening / closing. The backdraw is it only can be opened to the side, so you cannot expand down as far as I checked.

    I'm using it as a collapsible menu, opening by hovering your mouse on the chevron:

     

    image.png.cbbb76768d4263f4529851b06b1c49c5.png


  14. I really don't see the issue here. Pipe delimitation is not common; either search-replace with tabs and use any available database manager or write your own.

     

    Use FireDAC, Zeos or any SQLite.dll wrapper directly to "connect" to your database. If you choose a component-based approach you can load the contents in some kind of TDataSet-descendant and you can manipulate records as your heart desires.


  15. A ComboBox suffers from the same 2-click issue and while it does save space, still not the usual way to handle these inputs. If UI space is an issue you should be looking at how to increase the space, not on workarounds.

     

    Unfortunately at work people were doing something similar and just pulled things closer together when they ran out of UI space (or the infamous pagecontrols on tabsheets). The end result physically hurts to look at.


  16. I advise against the use of TCheckBox or similar for such an input. There are multiple reasons: "greyed" state doesn't clearly mean "not sure" AND you might have to click twice to change your answer from one answer to the other.

    I'd suggest to have three radio buttons, right next to each other, with each column having a title; like an online questionare.

     

    Somthing like this:

    image.thumb.png.3889e7bec572997b6e0008ff0a2b9689.png

    • Like 4

  17. If you are sure you can not put the component in sync mode somehow, what you can do is:

    - Create a thread, have a private boolean called "_requestcompleted"

    - Create the component in the thread's context

    - Set the event handlers, flip _requestcompleted to True in the handler when... well, the request is completed

    - in the thread's context, send the request and then have a loop like...

    Repeat
      // Message pump, if needed for the component
      Sleep(100);
    Until _requestcompleted Or Self.Terminated;

    This method is inefficient as the CPU is spinning in a loop but at least easy to understand. If your component needs no message pump, you can switch to events and use WaitForMultipleObjects for a more resource-friendly approach.


  18. You are talking about two completely different areas with completely different functionality.

     

    A component is displaying / allowing to change a value, The source of said value is the dataset, which can behave in multiple different ways... either send the data to it's connection, use CachedUpdates or simply Cancel and revert to the unchanged state.

    The connection will be the one deciding when the data will be written to the database by further caching and transactions.

     

    You don't want to mix the functionality, especially if that functionality already exists. Spend that free time further improving your component, to display and change a value only 🙂

×