TEdit select 点击时的文本就像 Chrome 和 Firefox 中的 URL 栏一样

TEdit select text on click like the URL bars in Chrome and Firefox do

我想要一个 TEdit 像 Chrome 和 Firefox 中的 Url 栏一样对点击做出反应。第一次点击时 select 所有文本和随后的点击删除 selection 如下所示:

我的做法:

// 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;

此代码未按预期工作,因为 edt_Search.SelLength 始终为 0。selection 将始终在 OnClick 事件即将被触发之前被清除。我已经尝试将此代码放入 OnMouseUpOnMouseDown 事件中,但问题仍然存在。

我该如何解决?有没有办法在不添加额外的 boolean 变量来保存当前状态的情况下做到这一点?

到 select TEdit 控件中的所有文本当控件获得焦点时只需处理 OnEnter 事件和 :

procedure TForm1.Edit1Enter(Sender: TObject);
begin
  PostMessage(Edit1.Handle, EM_SETSEL, 0, -1);
end;

您不能使用 Edit1.SelectAll,因为默认行为(发生在 OnEnter 之后)会清除编辑控件中的任何 select 离子。发布消息可确保在其余默认行为完成后对其进行处理。

为了在这些浏览器中完全模拟地址栏,该字段在退出控件时也会删除selects,所以在OnExit中:

procedure TForm.Edit1Exit(Sender: TObject);
begin
  PostMessage(Edit1.Handle, EM_SETSEL, 0, 0);
end;

浏览器字段还允许您在首次输入时 select 文本,因此在这种情况下您需要更加小心。作为黑客,您可以使用插入器来完成,但理想情况下您会制作自定义控件:

type
  TEdit = class(Vcl.StdCtrls.TEdit)
    private
      FDoEnterSelect : boolean;
  end;

然后

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;

KeyUp 处理程序处理跳转到控件的情况。唯一剩下的奇怪情况是编辑控件的 TabOrder 为零,因此在创建表单时聚焦(因此 selected)。这只会影响第一次单击控件。