如何让TMemo控件中Ctrl+A自动全选?

13

在Delphi 7的TMemo控件中,尝试使用键组合Ctrl + A选中所有文本无效(不会选中所有文本)。于是我写了这个过程:

procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
var
  C: String;
begin
  if ssCtrl in Shift then begin
    C:= LowerCase(Char(Key));
    if C = 'a' then begin
      Memo1.SelectAll;
    end;
  end;
end;

有没有什么技巧,让我不必执行这个步骤?如果没有,那么这个步骤看起来是否OK?


3
个人而言,我更愿意创建一个继承自标准备忘录的组件,并在那里处理按键,这样你就不需要在所有表单中添加特殊处理代码。 - David Heffernan
2
@David:你知道在多行模式下的标准Windows编辑控件是否禁用了Ctrl+A命令,或者是VCL包装器存在问题吗?(TEdit会像预期的那样处理Ctrl+A。) - Andreas Rejbrand
1
@Andreas 一旦我能够使用编译器的机器,我会尝试制作一个原始的win32 petzold程序并进行检查。 - David Heffernan
1
这似乎是一个没有记录解释的操作系统问题。许多关于它的帖子都只是基于“自己编写代码”的方式。 - TLama
2
@David:如果我没记错的话,Raymond 时不时会询问他的读者有什么要写的东西。这将是一个有趣的话题。 - Andreas Rejbrand
显示剩余4条评论
3个回答

29

这样更加优雅:

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
  if Key = ^A then
  begin
    (Sender as TMemo).SelectAll;
    Key := #0;
  end;
end;

4
可以,"^A" 是一个控制字符,通常用于命令行界面中,表示 "Control-A" 组合键。它可以将光标移到行首,也可以在一些程序中触发特定操作。 - David Heffernan
10
Ctrl+A键被表示为具有序号值1的字符(Ctrl+B为2,Ctrl+C为3,以此类推)。我认为这基本上是旧时代的遗物。这些“字符”通常被写成^A^B等形式,Delphi也支持这种表示法。你可以在ASCII表中看到它们,比如维基百科 - Andreas Rejbrand
2
好久没见过了,一定是从 TP 时代来的。 - Tony Hopkinson
5
@Jerry:结果并不完全一样。你的代码无法处理讨厌的“嘟”声! - Andreas Rejbrand
2
@Jerry - 据我所知,这个问题目前没有解决方案。这是Windows编辑控件的默认行为,您可以在此处阅读有关编辑控件预期行为的信息(http://msdn.microsoft.com/en-us/library/bb775460%28v=vs.85%29.aspx)。 - Sertac Akyuz
显示剩余9条评论

1
尽管Andreas Rejbrand的答案是正确的,但它并不符合Windows的视觉预期行为。这会使光标位置保持不变。Ctrl-A(全选)应该将光标保留在文本底部,并滚动控件以使光标可见。
如果没有这样做,控件会表现出奇怪的行为。例如,假设有比窗口更多的文本,且窗口未滚动到底部。你按下Ctrl-A,所有文本都被选择了。现在,Ctrl-C将把所有文本复制到剪贴板中。虽然你看不到,但光标现在位于视图底部,视图未滚动。如果现在按下Ctrl-Down,则所选文本仅成为可见文本,然后光标向下移动,窗口向下滚动一行。新的底行未被选中。这使得全选只选择了可见文本。
解决方法很简单,只需在SelectAll之前将插入符号移动到文本末尾即可。
procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
  if Key = ^A then begin
    With Sender as TMemo do begin
      SelStart := Length(Text);
      Perform(EM_SCROLLCARET, 0, 0);
      SelectAll;
    end;
    Key := #0;    //Eat the key to suppress the beep
  end;
end;

请注意,“吃掉键”仅在OnKeyPress事件中起作用,而不是在OnKeyDown或OnKeyUp事件中。

0
我使用之前的答案和讨论创建了一个独立的组件,用于处理KeyPress事件,并在小型测试程序中使用。
TSelectMemo = class(TMemo)
protected
  procedure KeyPress(var Key: Char); override;
end;

...

procedure TSelectMemo.KeyPress(var Key: Char);
begin
  inherited;
  if Key = ^A then
    SelectAll;
end;

另一种在表单的所有组件中添加“全选”行为的方法是在表单中添加一个带有标准全选操作的操作列表。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接