4
votes

I have a "username" TEdit on a Delphi 2006 login form. When the application starts up the user is asked to enter the username. The TEdit gets focus and the caret is placed in its horizontal center for some reason. As soon as anything is typed the caret is left aligned again and everything looks normal.

It is also strange that it wasn't always like this. This behaviour suddenly started a few years ago (I believe we still used Delphi 6 at that time). Any idea what might be causing this?

Additional info (has been asked for):

  • The problem is widespread: D2006 and D6 (I believe), 5 or 6 Delphi instances on as much computers, all applications using that login form. The effect is limited to the form however, it does not occur on other TEdits.
  • The TEdit is not filled with spaces (that would be strange to do in the first place).

  • More info (Nov 13):
  • The caret is not centered exactly, it is almost centered.
  • Currently it seems to occur in a DLL only. The same login dialog is used in regular executables and does not show the problem there (although I believe it did at some time).
  • The edit field is a password edit, the OnChange handler sets an integer field of that form only, there are no other event handlers on that edit field.
  • I added another plain TEdit, which is also the ActiveControl so that it has focus when the form shows (as it was with the password edit). I also removed the default text "Edit1". Now the issue is present in that TEdit in the same way.
  • The "centered" caret goes back to normal if either a character is entered or if I tab through the controls - when I come back to the TEdit it looks normal. This was the same with the password edit.
  • 5
    Can you provide us with the relevant pieces of the pas and dfm files?Toon Krijthe
    Added more questions, (we are getting somewhere).Toon Krijthe

    5 Answers

    2
    votes

    I had also the same problem in Delphi 2007,
    with a TEdit placed in a modal form called by double-clicking in a Grid.

    I made some tests launching the same Form from a TSpeedButton. I noticed that the problem with the TEdit appears only when the grid is focused.

    after more tests the problem appears to be a bug in the VCL.
    in TCustomGrid.paint there is a Call of SetCaretPos, even if the grid is not on an active Form.

          ../..
          Focused := IsActiveControl;
          if Focused and (CurRow = Row) and (CurCol = Col)  then
          begin
            SetCaretPos(Where.Left, Where.Top);          
            Include(DrawState, gdFocused);
          end;
          ../.. 
    

    the code above is from TCustomGrid.paint in Grids.pas in this code, Focused is set to true if the grid is the "activeControl" of the parent form, the code don't take into account if the form is active or not.

    then, if the grid need to be repaint, setCaretPos is called with grid coordinates, causing the bug mentioned in the question.

    The bug is very difficult to notice because, most of the times, the caret simply disappear from the active form instead of blinking near the middle of a TEdit.

    steps to reproduce the bug :

    1. start new VCL form app.
    2. add TStringGrid into it.
    3. add a second form to the app with just a TEdit in it.
    4. return in main form (unit1) and call form2.showmodal from the grid DblClick event.

    that's all : you can launch the application and double click on a grid cell. if you drag the modal form away of the main form, the grid will need to be repaint, then causing the caret to disappear from the modal form (or to appear in the middle of the TEdit if you are very lucky)

    So, I think a fix is needed in Grids.pas.

    in the excerpt of grid.pas above, I suggest replacing the call of the function IsActiveControl by a call of a new function called IsFocusedControl :

    // new function introduced to fix a bug
    // this function is a duplicate of the function IsActiveControl
    // with a minor modification (see comment)
    function TCustomGrid.IsFocusedControl: Boolean;
    var
      H: Hwnd;
      ParentForm: TCustomForm;
    begin
      Result := False;
      ParentForm := GetParentForm(Self);
      if Assigned(ParentForm) then
      begin
        if (ParentForm.ActiveControl = Self) then
          //Result := True;            // removed by DamienD
          Result := ParentForm.Active; // added by DamienD
      end
      else
      begin
        H := GetFocus;
        while IsWindow(H) and (Result = False) do
        begin
          if H = WindowHandle then
            Result := True
          else
            H := GetParent(H);
        end;
      end;
    end;
    

    this fix (made in Delphi2007) worked well for me, but is not garanteed.
    (also, do not modify directly units of the VCL).

    1
    votes

    Just a few additional questions:

    1. Is this problem on one pc or on more pc's?
    2. Does it occur on one application or on all applications?
    3. Does it happen only on your Delphi applications or on all applications?

    If it is only on one pc, I think it is a strange registry setting. If its on more pc's but you only have one delphi development pc, it could still be a registry setting. But there are other possibilities.

    You could try some tests:

    1. Create an simple app on the dev pc and run it on another. Does this show the effect.
    2. Use an app that is created by Delphi but build on another pc that does not show the effect, and run it on the dev pc, does this show the effect?

    I really think this is a registry setting. According to the information you gave me, it happened since Delphi 6 and is still happening. It also can be a locale setting but then it has to happen in more programs.

    Edit: Thanks for the extra info. So it looks like the problem can be isolated to a single form. But it occurs on all pc's.

    What you can do, is delete the edit, and re-add a new one. This saves searching for weird property values.

    • Are there events hooked on the TEdit that can possible explain the effects?
    • What property values are set? (But I prefer a look at the dfm and the code, because then I'm possible able to reproduce the effect.)
    0
    votes

    Are you sure it is a simple TEdit? It might be initialized with a few spaces instead of an empty string. The onChange handler then might just strip spaces as soon as you start typing. A TEdit extension might have text alignment set on centered instead of left, and set text alignment only on onChange.

    [edit] Please show the event handlers of the TEdit.

    0
    votes

    I've also noticed this behaviour in richedits.

    One place in our app is a double click on a grid which displays another screen containing a RichEdit. The caret always seems to appear in the Richedit in the same place as the double click on the grid occured, ie if the dblclick was on the 3rd line of the grid, the caret will appear ~3 lines down on the edit. As soon as a key is pressed, the caret resets to the correct position of top left.

    Its not limited to a certain form or pc as it happens on all developers machines and also on clients machines. The app was originally developed in Delphi 5, but the problem didn't occur (or wasn't noticed) until we moved to D2006.

    Its not a particularily big problem, just... irritating.

    0
    votes

    Another workaround:

    Before showing the second form, prevent the grid on the first form doing Paint action. Code snippet as below.

    Gird.BeginUpdate;
    
    try
    
      //Show the second form here
    
    finally
    
      Grid.EndUpdate;
    
    end;