Jump to content

Anders Melander

Members
  • Content Count

    2265
  • Joined

  • Last visited

  • Days Won

    117

Posts posted by Anders Melander


  1. Using a TImage for each image will probably consume far to many resources if you have a fair amount of images - or large ones.

     

    I would just use a TImageList, a TPaintBox and a TScrollBar:

    Store a thumbnail of the images in the imagelist.

    Use the scrollbar to control which image(s) to show.

    Draw the currently visible image(s) from the imagelist to the paintbox.

    • Like 1

  2. 2 hours ago, alogrep said:

    there was another FindFirst() very close to the first one  without FindClose().

    The next time you get a leak report from madExcept, double-click in the lower pane on the line that caused the leak and it will open up the unit in Delphi and place the cursor right where the allocation occurs:

    image.thumb.png.e62aafa962144a8916df57b16d16945a.png

    • Like 1

  3. 6 minutes ago, corneliusdavid said:

    if "FindFirst() = 0" returns false, then FindClose() is never called.

    From the documentation: "FindFirst allocates resources (memory) that must be released by calling FindClose"

    The documentation is partly wrong.

     

    FindFirst wraps the FindFirstFile Windows API function which documentation more correctly state:

    Quote

    If the function succeeds, the return value is a search handle used in a subsequent call to FindNextFile or FindClose, and the lpFindFileData parameter contains information about the first file or directory found.

    If the function fails or fails to locate files from the search string in the lpFileName parameter, the return value is INVALID_HANDLE_VALUE and the contents of lpFindFileData are indeterminate.

    So on failure there is nothing to free with FindClose; If you look at the source you will see that FindClose does nothing if the result of FindFirstFile was

    INVALID_HANDLE_VALUE.

     


  4. 9 hours ago, FPiette said:

    DWScript scriting language is easy to learn since it is almost Delphi language.

    The script language is easy but integrating DWScript into an application is hard; There is zero documentation and the examples are insufficient.

    I've used DWScript since Delphi 5 but I still find it hard to use.


  5. 1 hour ago, A.M. Hoornweg said:

    [Sleep] is perfectly OK if the thread has to do something useful periodically and if xxx isn't a terribly small number.

    I disagree. Sleep is only appropriate if the interval is very small and even then I wouldn't use it.

     

    The problem is thread termination; If you are using Sleep then the thread cannot be terminated while Sleep is executing.

    IMO the better solution, as have already been suggested, is to wait on an event with a timeout: If the event times out, do the task. If the event is signaled, terminate the thread. To terminate the thread, signal the event.

     

    While waiting on an event is much more complicated than just calling sleep, if one is to use threads one might as well learn how to do these things. Threads are difficult and pretending they aren't will just lead to lessons learned, the hard way, later on.

    • Like 2

  6. An easy way to introduce new methods and properties to components on a form is to use interposers:

    type
      TCheckBox = class(StdCtrls.TCheckBox)
      private
        FGroup: string;
        FValue1: string;
        FValue2: string;
      public
        property Group: string read FGroup write FGroup;
        property Value1: string read FValue1 write FValue1;
        property Value2: string read FValue2 write FValue2;
      end;

    Insert this in the interface section of your form unit. It must be before the declaration of the form.

    You can also put it in a separate unit but then you need to ensure that that unit is referenced after StdCtrls.

     

    Basically, this trick fools the Delphi DFM loader into creating an instance of your TCheckBox class instead of the standard one in StdCtrls.

     

    Note that interposers only enables you to extend a component at run-time. The design-time environment (i.e. the Delphi IDE) knows nothing about this trickery so the new properties will not appear in the property inspector (which is also why I didn't bother declaring them as published). If you want design-time support you will have to create and register a custom component the normal way.

    • Like 1
    • Thanks 1

  7. 1 hour ago, SwiftExpat said:

    Which open-source monospaced font is best for coding? | by Matej Latin | UX Collective (uxdesign.cc)

    Clickbait title and the author has no clue about the things he writes about.

     

    If it wasn't for the illustrations I'd thought that article was written by ChatGPT.


  8. 2 hours ago, MikeMon said:

    I am aware that DevExpress VCL 23.1 doesn't officially support Delphi 12. Has anyone found a workaround?

    Yes: Install v23.2.3

     

    There is no "workaround". To support Delphi 12 with an older version you would have to replicate the things they've done in 23.2 and then you might as well just install 23.2

    • Like 3

  9. 6 hours ago, A.M. Hoornweg said:
    
    Type tSomeclass<T:iInterface>=CLass (tInterfacedObject, iSomeInterface<T>)
         //many methods here
         Procedure SomeMethod(intf: T);
         Function SomeFunction:T;
         Constructor Create(someparameters);
         Function CreateNewInstance:iSomeInterface<T>;
      end;
        
      ...
      
      Function tSomeclass<T>.CreateNewInstance:iSomeInterface<T>
      begin
          result:=Self.Classtype.Create(fSomeParameters); //Does not compile
      end;
      

     

    I tHiNk YoU NeEd To DeBoUnCe YoUr ShIfT KeYs...

     

    I think you can get something to compile but even then I have a feeling that, whatever it is you are trying to do, isn't possible.

    FWIW, this one compiles:

    type
      IMyInterface<T> = interface
        function GetValue: T;
        function Clone: IMyInterface<T>;
      end;
    
      TMyClass<T> = class(TInterfacedObject, IMyInterface<T>)
      private
        FValue: T;
      private
        // IMyInterface<T>
        function GetValue: T;
        function Clone: IMyInterface<T>;
      public
        constructor Create(const AValue: T); virtual;
        function CloneObject: TMyClass<T>;
      end;
    
    function TMyClass<T>.Clone: IMyInterface<T>;
    begin
      Result := CloneObject;
    end;
    
    function TMyClass<T>.CloneObject: TMyClass<T>;
    begin
      Result := TMyClass<T>.Create(FValue);
    end;
    
    constructor TMyClass<T>.Create(const AValue: T);
    begin
      FValue := AValue;
    end;
    
    function TMyClass<T>.GetValue: T;
    begin
      Result := FValue;
    end;

     


  10. 1 hour ago, William23668 said:

    Any one know a good place to find remote work ?

    I don't, but I know how to let the remote work find you:

    • Answer questions on stackoverflow.
    • Answer questions here.
    • Participate in open-source projects.

    Of course, it helps immensely if you can do that within a narrow field of expertise (to minimize the competition) - or better than most.

    If you can stomach the self-promoting nonsense in the LinkedIn Delphi group you can also try posting there. I don't use it myself (as I wouldn't be able to behave).

     

    ...and start by changing your screen name. I assume your last name isn't 23668...

     

    If I wanted to I could live off the remote & freelance offers I get because my name comes up when clients google for info on some special tech they need help with.

    • Like 5

  11. 6 hours ago, gkobler said:

    the main changes are, first i open the FDQuery and copy the data to a FDMemTable, after that i close the FDQuery and my While loop are working with the TDMemTable dataset to with the query. So i got no exception and the UPDATE Statements is working well. Strange...

    You don't need to copy data from one FireDAC dataset to a TFDMemTable; All FireDAC datasets are mem-tables and can work in offline/briefcase mode.

    All you need to do is make sure you fetch all data from the server. Do a FetchAll like it said in the other thread posted.

    • Thanks 1

  12. Check ResourceOptions.CmdExecMode; It should not be amAsync. Sorry. You already checked that.

     

    If you can, monitor the activity on the SQL Server to see if there is activity on your connection that you can't account for.

     

    I still think it's MARS (I've been bitten by that one many times). I can't remember if it can be disabled on the server, but that's one thing to try (just to rule it out).


  13. 16 minutes ago, gkobler said:

    Connection is busy with results for another hstmt

    Did you Google the error message?

     

    As the error message hints at, it's a concurrency issue; Your application attempted to call the DB server with a request while the connection was busy with a prior request. This happens if you are executing statements asynchronously.

    If you have MARS enabled I believe that can also cause the problem. Disable it in your connection string.

×