Jump to content

Uwe Raabe

Members
  • Content Count

    2889
  • Joined

  • Last visited

  • Days Won

    169

Posts posted by Uwe Raabe


  1. There are several bugs fixed in 12.2 and 12.3 affecting frames.

    https://quality.embarcadero.com/browse/RSP-37402

    https://quality.embarcadero.com/browse/RSP-39847

    https://quality.embarcadero.com/browse/RSP-40110

    https://quality.embarcadero.com/browse/RSP-43560

    https://embt.atlassian.net/servicedesk/customer/portal/1/RSS-1020

     

    Perhaps these will fix your problem, too.

     

    I will test your project later when I've found some time to configure my system for monitors with different dpi.

    • Like 2

  2. 2 hours ago, jesu said:

    Yes, Windows 11 Notepad screws files. This never happened in Windows 10 after many years using it. You open a file double-clicking it, edit it and just click save expecting that it respects your encoding. Sometimes it does, sometimes not. Sure, you can use Save as to be sure that it uses the encoding you want, but that was never neccessary before.

     

    23 hours ago, jesu said:

    Unfortunately, we still need to use ANSI in some files but sometimes (likely by notepad) that is replaced with UTF8.

    I just took what the OP wrote and show a way to revert any file somehow changed from ANSI to UTF-8. I never said it is a silver bullet for all circumstances.


  3. 5 minutes ago, jesu said:

    The fact is that we need to restore these files without loosing time doing it by hand.

    Load the file with UTF-8 encoding and save it with ANSI encoding.

    uses
      System.IOUtils;
      
    ...
      TFile.WriteAllText(FileName, TFile.ReadAllText(FileName, TEncoding.UTF8), TEncoding.ANSI);

    If the files are too large to fit into memory, you need to work with different file names for input and output:

      var writer := TStreamWriter.Create(NewFileName, False, TEncoding.ANSI);
      try
        var reader := TStreamReader.Create(FileName, TEncoding.UTF8);
        try
          while not reader.EndOfStream do
            writer.WriteLine(reader.ReadLine);
        finally
          reader.Free;
        end;
      finally
        writer.Free;
      end;

     


  4. First, declare the message type in a common unit:

    type
      TIntegerMessage = class(TMessage<Integer>);

    Second, declare a TMessageListenerMethod in FormA handling that message type:

    type
      TFormA = class(TForm)
        ...
      private
        procedure MyMessageHandler(const Sender: TObject; const M: TMessage);
      ...
    
    procedure TFormA.MyMessageHandler(const Sender: TObject; const M: TMessage);
    begin
      var msg := M as TIntegerMessage;
      // do something with the Integer you get from msg.Value
    end;

    Third, subscribe/unsubscribe to this message type in TFormA.FormCreate/FormDestroy:

    procedure TFormA.FormCreate(Sender: TObject);
    begin
      TMessageManager.DefaultManager.SubscribeToMessage(TIntegerMessage, MyMessageHandler);
    end;
    
    procedure TFormA.FormDestroy(Sender: TObject);
    begin
      TMessageManager.DefaultManager.Unsubscribe(TIntegerMessage, MyMessageHandler);
    end;

    Finally, send the message in FormB:

    begin
      ...
      TMessageManager.DefaultManager.SendMessage(Self, TIntegerMessage.Create(42));
      ...
    end;

    Note: Only the common unit with the type declaration has to be used by both form units. None of them needs to use the other form unit.


  5. The value of calculated fields are only stored for the current record. As soon as you move to another one, the field content is lost. Therefore you need to calculate the field value several times, which can slow down performance when the calculation needs some time. A solution is to cache these values.


  6. 16 minutes ago, Squall_FF8 said:

    Does anybody knows why we have such weird execution order: Calc, AfterOpen, Calc?

    Calculating fields is done on each record at several occasions. Any change to the current record, be it by navigating or switch to and from edit mode. AfterOpen is dataset based and when it is called, at least the first record is already loaded and all fields contain their values, including the calculated ones.

    • Thanks 1

  7. The TGlyph type being private and Glyph property being protected makes everything a bit cumbersome. Fortunately there is a trick to inject a message handler without subclassing.

    type
      TEditButtonHelper = class helper for TEditButton
      public
        procedure LinkMessageHandler;
      end;
    
      TGlyphMessageHandler = class(TWinControlMessageHandler)
      protected
        function HandleMessage(var Message: TMessage): Boolean; override;
      end;
    
    function TGlyphMessageHandler.HandleMessage(var Message: TMessage): Boolean;
    begin
      var edt := TButtonedEdit(Control.Parent);
      case Message.Msg of
        WM_LBUTTONDOWN: edt.PasswordChar := #0;
        WM_LBUTTONUP: edt.PasswordChar := '*';
      end;
      Result := inherited;
    end;
    
    procedure TEditButtonHelper.LinkMessageHandler;
    begin
      Glyph.InitMessageHandler(TGlyphMessageHandler);
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      ButtonedEdit1.RightButton.LinkMessageHandler;
    end;

     

    • Like 1

  8. The buttons of a TButtonedEdit are no controls, so there simply is no handle. Instead they provide an instance FGlyph of a private type TGlyph derived from TCustomControl, which handles the mouse events. This control has the edit control as parent.

     

    Perhaps you can achieve your goal by deriving from TButtonControl and override GetEditButtonClass. This gives you access to the protected FGlyph and allows to replace it with a derived class implementing the requested behavior.


  9. If Image1.Picture.Graphic is not of type TBitmap, referencing Image1.Picture.Bitmap will clear the current content and create an empty TBitmap.

    • Like 2
    • Thanks 1

  10. 47 minutes ago, Lajos Juhász said:

    You can save the form, close all the projects and open the form the IDE will remove the reference to the datamodule and you will not see the pictures anymore.

    I doubt that is correct. The datamodule dmSharedImages containing the image lists is part of GExpert and as long as GExpert is loaded in the IDE the datamodule exists and the references are resolved. The problem happens during runtime only.

     

    BTW, 3rd party plugin developers should be aware of this and name their forms, frames and datamodules with in mind.

×