delphiframetbuttonededit

Delphi: ButtonedEdit + Frame = Bug


Delphi XE.

There is a Buttoned Edit (with the left button), an image list with a picture for the button. All is on a frame (it is Ok if on a form).

There is no an indent of the button in a design time, but it is in a run time.

Is it a bug?

enter image description here enter image description here

Thanks!


Solution

  • Yes it's a bug. For some reason the Ctl3D property of the TButtonEdit is not being streamed correctly from the .dfm file when the edit resides in a frame. The streaming is resulting in Ctl3D being False instead of True.

    Then, in TEditButton.UpdateBounds the following code executes:

    if (not FEditControl.Ctl3D) and (FEditControl.BorderStyle <> bsNone) then
    begin
      FGlyph.Top := 2;
      Inc(NewLeft, 2);
    end;
    

    This is what is shifting the position of your button 2 pixels right and down.

    You can work around the bug by manually setting Ctl3D in code and forcing UpdateBounds to be called again. I did this with an interposer:

    type
      TButtonedEdit = class(ExtCtrls.TButtonedEdit)
      protected
        procedure Loaded; override;
      end;
    
    procedure TButtonedEdit.Loaded;
    begin
      inherited;
      Ctl3D := True;
      LeftButton.Visible := not LeftButton.Visible;
      LeftButton.Visible := not LeftButton.Visible;
      RightButton.Visible := not RightButton.Visible;
      RightButton.Visible := not RightButton.Visible;
    end;
    

    You can include this in your frame, but make sure that the declaration of the interposed TButtonedEdit is before your frame is declared. Or if the bug afflicts many frames, declare it in a common unit and use that unit in your frame after you use ExtCtrls.

    Now, as for the obvious question as to why the streaming doesn't set Ctl3D correctly, I have no answer for that. Perhaps someone more knowledgeable than I am about form streaming could enlighten us!