0
votes

I placed a TEdit control on a form, for a password. My aim is, let the TEdit control show asterisks when it's not focused, to avoid other people seeing it, and reveal the password to allow editing when focused.

To achieve this, I added OnEnter and OnExit handler to set PasswordChar property to #0 and '*' accordingly.

This worked well in Delphi 7, but went wrong in Delphi XE seattle, the TEdit control went into a strange state that it didn't show the blinking edit cursor, nor the highlighted blue backgrounded selection after the OnEnter event triggered (in which the PasswordChar is set to #0).

I stepped into the TEdit control source code in debug mode, and found the TEdit control will recreate its some handle (I don't know much of Windows API) when setting PasswordChar. I guess this caused the problem, but not sure, and don't know how to avoid it.

Please help me out of this, I've tried a lot and didn't find a way.

Here is the simplest test program:

type
  TTestForm = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Edit1Enter(Sender: TObject);
    procedure Edit1Exit(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  TestForm: TTestForm;

implementation

{$R *.dfm}

procedure TTestForm.Edit1Enter(Sender: TObject);
begin
  Edit1.PasswordChar := #0;
end;

procedure TTestForm.Edit1Exit(Sender: TObject);
begin
  Edit1.PasswordChar := '*';
end;

end.

dfm:

object TestForm: TTestForm
  Left = 0
  Top = 0
  Caption = 'TestForm'
  ClientHeight = 242
  ClientWidth = 472
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Edit1: TEdit
    Left = 72
    Top = 48
    Width = 225
    Height = 21
    PasswordChar = '*'
    TabOrder = 0
    Text = 'You can not see text selection'
    OnEnter = Edit1Enter
    OnExit = Edit1Exit
  end
  object Edit2: TEdit
    Left = 72
    Top = 75
    Width = 225
    Height = 21
    TabOrder = 1
    Text = 'Click this control to trigger TEdit1.OnExit'
  end
end
1

1 Answers

1
votes

You can clear ES_PASSWORD style with EM_SETPASSWORDCHAR message. This keeps edit in a normal state. But then in OnExit you need to set passwordchar twice in order to edit to recreate its window. Or you could use some hack control to get access to RecreateWnd procedure (so it wouldn't create it's window twice).

procedure TTestForm.Edit1Enter(Sender: TObject);
begin
  SendMessage(Edit1.Handle, EM_SETPASSWORDCHAR, 0, 0);
end;

procedure TTestForm.Edit1Exit(Sender: TObject);
begin
  Edit1.PasswordChar := #0;
  Edit1.PasswordChar := '*';
end;