Short Version
How can i select all text in a TEdit when the control gains input focus from the user clicking the edit box?
Motiviation
Following the Windows User Design Guidelines for a "search" box:
Interaction
On input focus, automatically select any previously entered text. Doing so allows users to enter a new search by typing, or to modify the previous search by positioning the caret using the arrow keys.
That is my hypothetical reason; but i don't need a reason. I just need the behaviour i'm asking for, which is the behaviour of Windows (see Windows Explorer).
Research Effort
We all know that SelectAll property:
Determines whether all the text in the edit control is automatically selected when the control gets focus.
Set AutoSelect to select all the text when the edit control gets focus. AutoSelect only applies to single-line edit controls.
Use AutoSelect when the user is more likely to replace the text in the edit control than to append to it.
And that does work; but only when:
- the edit control gains input focus through the Tab key
- or through a call to SetFocus
It doesn't work if the user's clicks the control to give it input focus (meaning that this portion of the documentation above isn't, strictly speaking, correct).
What have you tried?
Edit1.AutoSelect := True;Simply does not work.
OnEnter call SelectAll
procedure TForm1.Edit1Enter(Sender: TObject); begin Edit1.SelectAll; end;it simply does not work; presumably for the same reason AutoSelect doesn't. Without debugging the VCL, i assume that it is selecting all, but then a click is registered and that tries to set the caret; clearing the selection.
OnClick call SelectAll
procedure TForm1.Edit1Click(Sender: TObject); begin Edit1.SelectAll; end;That doesn't work because it calls SelectAll every time the user clicks, rather than when the edit control gains input focus (i.e. clicking to set the caret position re-selects all—not what we want.
OnClick call SelectAll with focus check
procedure TForm1.Edit1Click(Sender: TObject); begin if not Edit1.Focused then Edit1.SelectAll; end;By the time OnClick is called, Focused is already true.
OnMouseDown with Focus check
procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if not Edit1.Focused then Edit1.SelectAll; end;Doesn't work because by the time MouseDown is called, the control already has focus.
The Question
Which brings us back to the question:
- How to SelectAll text when a TEdit control gains input focus by the user clicking?
And for reference: the Windows control selects all text before the mouse is released. I feel like it needs an ugly hack of:
- catch WM_SETFOCUS
- somehow know if focus came from mouse (rather than keyboard navigation, or programmatic) and set a flag
- if the flag was set: eat the next MouseDown/MouseClick
But i feel like that is fraught with eating user mouse clicks if it is not done correctly; which is even worse.
Bonus Reading
- TEdit onclick select all? (has a different ask; wants to always select all text every click. Definitly not what we want, or what Windows does)
CRME
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure Edit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
// Edit1.SetFocus;
end;
procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
// if not Edit1.Focused then
// Edit1.SelectAll;
end;
end.

EDITcontrol (whichTEditis a thin interface to) doesn't behave like that. Modern Windows apps, on the other hand, don't use the classic desktop controls at all, so they are different. Still, if I enter a search text in the Windows Explorer search field (top-right corner), move focus away from the search box, and then click the search box again, the text isn't selected. The behaviour is like that of a standardTEdit.IsDialogMessageis sufficient or if you have to sendWM_GETDLGCODEmessages and respond accordingly.procedure TEdit.WMSetFocus(var Message: TWMSetFocus); begin inherited; PostMessage(Self.Handle, EM_SETSEL, 0, -1); end;does the trick.TEditExcontrol (maybe with a published boolean propertyAlwaysAutoSelect(orClickAutoSelect)) and register it in the IDE.