I want to have a TEdit
that reacts on a click like the Url bars in Chrome and Firefox. On first click they select all text and following clicks remove the selection as shown here:
My approach:
// This method is bound to the OnClick event
procedure TForm.edt_SearchClick(Sender: TObject);
begin
if edt_Search.SelLength > 0 then
edt_Search.SelLength := 0
else
edt_Search.SelectAll;
end;
This code doesn't work as expected as edt_Search.SelLength
is always 0. The selection will always be cleared before the OnClick event is about to be triggered. I've already tried to put this code into the OnMouseUp
and OnMouseDown
events but the problem stays the same.
How can I solve it? Is there a way to do this without adding an additional boolean
variable which saves the current state?
To select all text in a TEdit
control when the control gains focus simply handle the OnEnter
event and :
procedure TForm1.Edit1Enter(Sender: TObject);
begin
PostMessage(Edit1.Handle, EM_SETSEL, 0, -1);
end;
You cannot use Edit1.SelectAll
since default behaviour (which happens after OnEnter
) clears any selections in the Edit control. Posting the message ensures that it gets handled after the remaining default behaviour completes.
To fully emulate the address bar in those browsers, the field also deselects when exiting the control, so in OnExit
:
procedure TForm.Edit1Exit(Sender: TObject);
begin
PostMessage(Edit1.Handle, EM_SETSEL, 0, 0);
end;
The browser field also allows you to select text when first entering, so in this case you need to be a bit more careful. As a hack you can do it with an interposer, but ideally you'd make a custom control :
type
TEdit = class(Vcl.StdCtrls.TEdit)
private
FDoEnterSelect : boolean;
end;
and then
procedure TForm1.Edit1Enter(Sender: TObject);
begin
Edit1.FDoEnterSelect := true;
end;
procedure TForm1.Edit1Exit(Sender: TObject);
begin
PostMessage(Edit1.Handle, EM_SETSEL, 0, 0);
end;
procedure TForm1.Edit1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Edit1.FDoEnterSelect and
(Edit1.SelLength = 0) then
PostMessage(Edit1.Handle, EM_SETSEL, 0, -1);
Edit1.FDoEnterSelect := false;
end;
procedure TForm1.Edit1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
Edit1.FDoEnterSelect := false;
end;
The KeyUp
handler deals with the case of tabbing to the control. The only remaining odd case is if the edit control has TabOrder of zero and, therefore, is focused when the form is created (and therefore selected). This would affect the first click into the control only.