Jump to content

PeterBelow

Members
  • Content Count

    460
  • Joined

  • Last visited

  • Days Won

    13

Posts posted by PeterBelow


  1. 3 hours ago, PeterPanettone said:

    $Selection Macro would be very helpful. It would allow the creation of Tools that process the text selected in the Editor.

    How could it deal with selections spanning multiple lines or columns? That cannot be handled as command-line parameters. Just hitting Ctrl-C and launching a tool that processes the content of the clipboard and puts the modified text back on it, then pressing Ctrl-V is much more flexible, IMO.


  2. 22 hours ago, direktor05 said:

    Hello,

     

    Im calling a DLL written in Delphi, when exiting form I get Access Error. How to deal with debugging of this kind of errors when you don't know exactly what is wrong but only get memory location access error? I think there is a problem with memory management, loading and unloading, creating and destroying components. But where....? Are there any tools to better analyze this? I'm using Delphi 11.3

     

    Help is very welcome.

    Are you calling the DLL from a Delphi app or some other environment?

    Anyway, even if you use a DLL from a host app made with the same Delphi version it is not safe to pass data types to the DLL for which the compiler does automatic memory management (string, dynamic arrays, objects that internally use such data types, e.g. TStringlist). At minimum you have to use the SimpleShareMem or ShareMem unit on both sides to get both modules to use the same memory manager. This may not be enough if the DLL implements forms or datamodules, since these use global VCL variables like Application and Screen, of which each module has its own instance. The only way to make both modules share the same VCL instance is to build both with the core RTL and VCL run-time packages.


  3. 3 hours ago, sp0987 said:

    We have introduced a new variable to the interface part and a function to the implementation portion of the Delphi 11 System.Sysutils.pas, in accordance with project requirements. The freshly generated variable is not accessible to me, and when I try to access it, I get the "Undefined Identifier" error. In Delphi 7, the same procedure was effective.

    If you changed the interface section (bad idea, really) that means that every RTL and VCL unit using system.sysutils needs to be recompiled in addition to your own units and the resulting dcus need to be put in a folder where they replace the dcus that come with the Delphi installation. And remember that said installation has different dcus for debug and release and different platforms, something D7 did not have.

    Best reevaluate the original cause for this change in D7 and see wether you can avoid it in D11 completely.

    • Like 7

  4. 12 hours ago, marcocir said:

    Hi all.

     

    After successfully installing CEF4Delphi on Delphi 12.1, same package in Delphi 11.3 raised an error at startup.

    Now, every attempt to reinstall it on Delphi 11.3 results in the same error, specifically during the installation of the design-time BPL.

     

    Clip4.thumb.png.cfdb36224779d4fe3c456bc9124fa288.png

     

    Any help?
    Thanks
    Marco

     

     

    Looks like the design-time package in the D11 folder (22.0 is the folder for that version) is in fact the version for D12, that is, should be in the 23.0 branch. But it may also be the correct version but tries to load a run-time package from the wrong folder. That is a common problem if the packages are not named properly with a version tag (280 for D11, 290 for D12). Run-time packages are loaded using Window's search strategy for DLLs (since they are DLLs in fact), which includes searching folders on the PATH. If you have several RAD Sudio versions installed each will have its BPL folder on the path, so the search may find the wrong version of a package if they all have the same filename.

    A possible cure is to move the run-time package in question to BIN folder of the matching Delphi version (where bds.exe resides), since Windows  searches that folder first. Another is to start the IDE not via the start menu links the installer created but from a batch (cmd) file where you first redefine the PATH to only contain the folders for this Delphi version.

     

    Oh, and if you can rebuild the packages you can of course change the project options to use the proper version tags for the produced binaries.


  5. 17 hours ago, msi1393 said:

    Hello I need to use of C# Dll in my Delphi program

    i use of delphi 10.4
    is this possible?
     If there is, please explain me step by step

    If the DLL is COM-enabled you can use the Component -> Import component dialog from the IDE main menu:

    image.thumb.png.a12c4f12a66c5a8911f1a6442b630c9e.png

     

    A pure .NET assembly without COM support cannot be used from Delphi with the tools available out of the box, but there are 3rd-party libraries available, some freeware.  A google search for "host the .net framework in delphi" turns up this for example. I have no personal experience with such libraries.

     


  6. Have you configured the IDE to load the last open project at start? The message may be caused by a corrupted dproj file.

    If you get the error without loading a project check the registry key Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Embarcadero\BDS\23.0\Personalities. It should look like this:

    image.thumb.png.2fb103f22dd97e18401263dcbcfe2dfd.png

    Depending on your licence you have more entries, but the one after "(Standard)" is what counts here.

    There is a matching key for the current user: Computer\HKEY_CURRENT_USER\SOFTWARE\Embarcadero\BDS\23.0\Personalities. It should have the same content.


  7. On 4/13/2024 at 10:50 PM, cecarnicom said:

    OK, I have solved it.  Very strange solution to me, but problem is definitely tied into the default setting of 16x16 height width in the imagelist component.  I set to maximum allowable of 256 x 256 pix and now the images are loading quite fair.  I find it surprising that a 256 pix max condition exists, and even though it is far short of rather modest image display desired of 600 pix, it will still work fine for my current need.  Ok for now, but still a mystery to me why such low limits would exist for an image component, and why they are set as the default, and what is the actual resolution limit and capacity of display.  Able to move on the next higher priority now though, thanks much,  Best regards, from Clifford.

    The reason is quite simple: the component is based on a Windows common control which is intended to serve as storage for small images/icons used for menu items, buttons, listview items. To reduce the consumption of GDI handles the control merges all added bitmaps into one large bitmap for storage. That's the reason all bitmaps added are forced to the same size, this way the imagelist can calculate where on the combined bitmap each image resides and then paint that part to the target location. There is a maximum size to a GDI bitmap, so this puts limits on the size and number of the images you can put into a TImagelist.

    Looks like the control is simply not suitable for your task.

    • Like 2

  8. Stretching bitmaps to a larger size (e.g. a 16x16 bitmap to 64x64) has this effect. The Windows API function used by the VCL is not very good at reducing the unavoidable degradation in image quality by interpolating the new pixels added between the original ones. You get much better results using vector formats like SVG as source, which can be rendered to practically any size without quality loss as long as the aspect ratio is not too far off the original.

     

    For bitmaps used for UI elements (buttons, menus, listview items etc.) Delphi offers TImageCollection and TVirtualImagelist. The former can store multiple versions (different sizes) of an image and the latter is used to then pick the best fitting version for a particular screen resolution.


  9. 20 hours ago, VilleK said:

    After updating to 12.1 I can no longer use the "Evaluate/Modify" feature (ctrl + F7). I get the message "Cannot load evaluator". Does it work for anyone else?

     

    This is a big issue for me because Ctrl + F7 is my main debugging tool and I've been using that shortcut since the Turbo Pascal days.

     

     

    Works for me without problems (Win32 project with debug build, halted on a breakpoint). But dcc32270.dll does not belong to Delphi 12.1, that uses dcc32290.dll. 270 would be Delphi 10.3 if memory serves.

    Check the registry key HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Embarcadero\BDS\23.0\Debugging\Embarcadero Debuggers\Evaluators, that names the defaullt debug evaluator.

    image.thumb.png.929d7865bf18cbfde573ddf7474de60e.png


  10. 14 hours ago, MarkShark said:

    Hi all!  Is there a library routine or api function that will compare two utf8 strings or buffers without converting them to UTF16?   I'm looking for something analogous to AnsiCompareStr.  Thanks!

     

    -Mark

     

    Depends on what you need to compare for. Equality is easy, that is a simple memory comparison. Larger/smaller implies a collation sequence, which is language-specific. Here converting to UTF-16 first is, in my opinion, the only practical way. Same if you need case-insensitive comparison, since case conversion is also language-specific and may not be applicable for the language in question at all (e.g. chinese).


  11. 8 hours ago, Noor said:

    Hello everyone,

     

    I'm seeking insights on database development practices in Delphi with Firebird. I have two specific questions:

     

    • When it comes to database development in Delphi, what is the recommended approach: utilizing data-aware components like drag-and-drop fields and linking with TFDQuery for CRUD operations, or segregating CRUD operations into separate units for forms? I'm particularly interested in understanding the balance between ease of use, efficiency and code usability. Any insights or examples you can provide would be greatly appreciated.
    • Often, we encounter situations where we need to fix a bug or implement changes in just one form out of many (over 100 forms) within our system. Currently, we update the complete executable, which includes all VCL forms in one project. What would be the best approach to handle such incremental updates efficiently without impacting all clients? I'm eager to learn about effective strategies in this scenario.

     

     

    Thank you for your valuable input.

    Warm regards,
    Noor

    Oy, that's a really open-ended subject. The RAD approach (using data-aware controls and connection/query components you create and configure at design-time) gets you results (= working application) fast but it tends to get messy fast as well, with business logic mixed into form and data moduls, poor reuse of code (unless you plan well ahead). This approach makes proper separation of application layers harder and is excellent at producing apps that are a nightmare to maintain and document. Code can be written to be self-documenting and serve as source for project documentation as well, but how do you deal with all the stuff set at designtime and scattered across dozens or even hundreds of dfm files?

     

    In my opinion RAD is workable for smaller projects with a few database tables and a few forms as well. For anything more complex and expected to have a lifetime of many years with frequent updates it pays to use a proper layered approach (e.g. model-view-controller or similar), with a object-relational mapper (ORM) as interface to the database and a client UI that works with data objects instead of directly talking to database tables, queries, or stored procedures. All the FireDac stuff would be hidden inside the ORM.

     

    Unfortunately Delphi does not come with an ORM, but there are some 3rd-party offerings in that area, including open-source projects like MORMOT. The learning curve can be steep if you have never dealt with such a design before, but it is worth it IMO. I wrote my own ORM for a larger project at work 20 years ago, took about half a year (part time, programming was not my main task) since nothing suitable was available at that time. It has served me well and some of the programs are still in some use...

     

    As for partitioning the app into modules that can be maintained independently: that is what packages are for, but it is not as straightforward as one would hope. It's DLL hell in disguise :classic_dry: and you have to invest some serious though into how you partition your application. Packages are all or nothing, every unit used can only be contained in one single package. All other units requiring such a unit have to get it from the (shared) package, so you have to deploy not only your own packages but also all used RTL and VCL (or FMX) and 3rd-party packages.

    As long as you do not change anything in the interface part of a packaged unit you can replace the build package in the production app with an updated package. If you change an interface you have to rebuild all packages using the modified one, plus the host app. Since forms etc. are declared in a unit interface that severely limits what you can change in such a form unit without major hassle.

     

    Note that this applies to units you want to use from other packages directly. It does not apply to units only used internally by a package. So it is possible to achieve a better isolation of modules if the only exposed part is a factory function for an interface the host app then uses to talk to the internal stuff of the package. In this scenario you can get away with only building with the core RTL and VCL packages and one shared package declaring the interface types used, and actually you can use DLLs (build with packages) instead of full-fledged packages. But this can still degenerate into a maintenance nightmare if you are nor careful...

    • Like 1

  12. 6 hours ago, pcoder said:

    Has anyone seen the case of globalSize() returning more than the requested size?
    It would be much more useful to get the requested size (<= allocated size) to determine the clipboard data size,
    but unfortunately I've found contradicting statements about globalSize().

     

    Pro allocated size:
    learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalsize
    stackoverflow.com/questions/22075754/how-do-i-determine-clipboard-data-size

     

    Pro requested size:
    devblogs.microsoft.com/oldnewthing/20120316-00/?p=8083
    www.labri.fr/perso/betrema/winnt/heapmm.html
    www.joelonsoftware.com/2001/11/20/a-hard-drill-makes-an-easy-battle/

    GlobalAlloc rounds the requested size up to the next multiple of 8 (at least), so it is normal for GlobalSize to return more than the requested size if that is not a multiple of the used granularity. In fact the MS docs for GlobalAlloc explicitely state that GlobalSize should be used to get the allocated size of the block requested. Depending on the use of the block you may have to store the actual data size with the data itself if the extra bytes allocated by GlobalAlloc may cause a problem for the data recipient.

    Note that the granularity used may depend on OS version, Microsoft is pretty vague on this.


  13. 2 hours ago, PeterPanettone said:

    This is not concisely logical, as it should word-wrap the Caption when the "text is too wide for the control" AND NOT PREVENT the word-wrap when it is already Multi-Line (if WordWrap = False).

     

    And, from a purely practical point of view, what sense would it make to explicitly truncate the text if it's too short for the control? Wouldn't it rather be more practical to automatically word-wrap the Caption when the text is too short for the control?

    It may not be logical but Windows has a lot of these little inconsistencies that have accumulated over time by bolting more functionality on existing control classes. TButton is a wrapper around the Windows button control, and its behaviour is determined by the set of button control styles, in this case the BS_MULTILINE style, which the Multiline property surfaces.


  14. 4 hours ago, davornik said:

    I am using DateTimePicker1.Format as ' ' to set the value to an empty string in TDateTimePicker (using it as dtkDate).

    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      DateTimePicker1.Format:=' ';
    end;
    
    procedure TForm1.DateTimePicker1Change(Sender: TObject);
    begin
      DateTimePicker1.Format:='';
    end;
    
    procedure TForm1.btnResetClick(Sender: TObject);
    begin
      DateTimePicker1.Format:=' '; //set as Empty
      DateTimePicker1.Date:=Date;
    end;

    Change event does not fire if I select today's date. How can I detect a click on the calendar if today's date is selected or clicked somewhere in the calendar itself?

    The control (a Windows common control under the VCL surtace) has no real concept of an "empty" state. The usual way to use it is to set the shown date to Today (it does that by default if memory serves) and accept that if the user does not change it. If your requirements really need a way to detect that the user has entered a date you can use an additional TCheckbox that disables the picker unless it is checked.


  15. 13 hours ago, bdw_nz20 said:

    I've just been playing a little bit with one of our applications to allow HDPI, not done much on this till now.

     

    Its working when changing the scaling for all windows i.e. change it in the display settings to 125%, 150% etc.

     

    I was just wondering if it was possible, like other applications can, to just adjust the VCL application rather than all windows.

     

    For example some windows allow Ctrl+ and Ctrl- keys to scale up and down of the window.

     

    You can experiment with the ScaleBy method all TWinControl descendants inherit, including forms.


  16. 13 hours ago, EugeneK said:

    I'm not saying doing it without interface, I mean hiding this implementation detail from the users. I.e. not allowing to manually implement this interface in code. This won't break any documented uses of anonymous methods.

    But that's the way it currently works! Of course you can design your own interface + implementor that acts exactly like anonymous methods act now, but that would still not be the same implementation the compiler creates behind the curtain now.


  17. 20 hours ago, Clément said:

    The unit I'm tracking does not appear in the graph.

    If I remove the path or rename the unit the project doesn't compile.

    I deleted all dcus from the library root to be sure only valid ".pas" files are compiled.

    But the compiler error message should pinpoint the uses clause the  (now missing) unit appears in, no?


  18. 3 hours ago, PeaShooter_OMO said:
    
    type
      TMyRec = record
        Int : Integer;
        Str : String;
      end;
      PMyRec = ^TMyRec;
    
    var
      LPointer : Pointer;
    begin
      New(PMyRec(LPointer));
      PMyRec(LPointer)^.Int := 200;
      PMyRec(LPointer)^.Str := 'Blah';
      Dispose(PMyRec(LPointer));
    end;

    I do not know why this approach bothers me but for some reason it does. I am casting a Pointer to a PMyRec to use it with New() and Dispose().

     

    I do not get a memory leak from this so I am assuming it will be operating correctly. Am I right?

     

     

     

    It will work but there is no point in doing it this way. Declare LPointer as type PMyRec and work with that. Don't use C idioms with Delphi, that only confuses things.


  19. On 3/12/2024 at 12:35 PM, Andrew Spencer said:

    Using Delphi 11.3

    I often have a situation where the .Visible property of a control depends on the .Checked property of a TCheckBox (or similar). To do this, I typically write an OnClick event for the TCheckBox, and set the .Visible property of the target control in a single line of code

    e.g.

    TargetLabel.Visible := SourceCheckBox.Checked;

    I also make sure to call this OnClick event at startup, if I happen to need to load the .Checked state from a previously-saved registry or Ini file entry.

     

    I thought that LiveBindings was designed to help me get rid of needing to write OnClick events. So to test I set up a TForm with a TLabel and a TCheckBox, with LiveBindings Designer as follows:

    image.png.d2dc98ef782e21938330c8b339a503b1.png

     

    My expectation was that, from then on, the TLabel.Visible property will simply follow the state of the TCheckBox.Checked property. No additional code would need to be written.

     

    BUT, it didn't work exactly as I expected.

     

    Question 1 : When I run this, the TCheckBox.Checked property initialises to the Design-time setting of TLabel.Visible. Setting TCheckBox.Checked to True at Design-time is ignored. Why is it not the other way around i.e. The TCheckBox.Checked value, at Design-time, determines the TLabel.Visible property at Run-time? That's the way that the arrow is pointing. This only appears to happen AFTER the application is up and running i.e. clicking on the TCheckBox will alter the visibility of the TLabel accordingly.

     

    Question 2 : How can I get this initialised, at run-time, so that the two controls start off operating correctly? I have only found that setting BOTH the TCheckBox.Checked AND the TLabel.Visible properties to the same value gets things going correctly.

     

    Question 3 : Programatically changing the TCheckBox.Checked state at runtime does not cause the TLabel.Visible property to change.

     

    Question 4 : Have I just totally misunderstood what I can do with LiveBindings, or how to implement what I want?

     

    If this is for VCL: I centralize such code by overriding the UpdateActions method of the form and updating the control states from there. Much easier than fiddling with multiple event handlers or live bindings.


  20. 4 hours ago, jesu said:

    Hello This code:


     

    
      if MessageDlg('Welcome to my Delphi application.  Exit now?',
        mtConfirmation, [mbYes, mbNo], 0, mbYes) = mrYes then
      begin
        MessageDlg('Exiting the Delphi application.', mtInformation,
          [mbOk], 0, mbOk);
        Close;
      end;
    

    shows icons in previous versions, but not in Delphi 12.

    This is too obvious to be a bug. Am I missing something?

    Thanks.

     

    This has come up before. Microsoft changed the UI guidelines and now recommends to not show an icon for confirmation dialogs. D12's vcl.dialogs unit was modied accordingly.


  21. 12 hours ago, Clément said:

    Hi,

    I'm using D12 for this project. I'm using VCL Styles, but the same behavior happens without styles.


    The first icon will call TFileOpenDialog.Execute. During this call, both TitleBarPanel.Caption and the button.caption icon "blink".

    Why is that?

     

     

    Here's the code:

     

    
    procedure TfrmMain.btnLoadFolderClick(Sender: TObject);
    begin
      FileOpenDialog1.Options := [fdoPickFolders];
      fLogFiles.edtLogFiles.BeginUpdate;
      try
        // Flicking starts
        if FileOpenDialog1.Execute then begin
        // Flicking ends
           var lEncoding := fEncodingList[fCurrentEncodingIndex];
           {...}
     finally
     end;
    end;

     

    You should not show a dialog inside a BeginUpdate/EndUpdate block in my opinion. That may be the source of your problem and it also serves no purpose i can see here.


  22. 25 minutes ago, dormky said:

    The TLabel was just for demonstration purposes, I'd like to be able to do that with all components...

    You cannot, it is only possible for TWinControl descendants.

    • Like 1
×