Delphi 在TForm.OnKeyDown中使用KeyPreview处理密钥不适用于TListBox

Delphi 在TForm.OnKeyDown中使用KeyPreview处理密钥不适用于TListBox,delphi,onkeydown,delphi-10.1-berlin,keypreview,Delphi,Onkeydown,Delphi 10.1 Berlin,Keypreview,A.创建VCL表单应用程序 B.在表格上放置一个TListBox,并在设计时填写一些项目,例如: C.将表单的KeyPreview属性设置为True: D.在表单的OnKeyDown事件处理程序中编写以下代码: procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key = VK_BACK then begin if ListBox1.Focuse

A.创建VCL表单应用程序

B.在表格上放置一个TListBox,并在设计时填写一些项目,例如:

C.将表单的
KeyPreview
属性设置为
True

D.在表单的
OnKeyDown
事件处理程序中编写以下代码:

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_BACK then
  begin
    if ListBox1.Focused then
    begin
      Key := 0;
      CodeSite.Send('ListBox1 is focused!');
    end;
  end;
end;
E.运行程序,点击项目5选择:

现在ListBox1有了焦点

F.现在按退格键。假定,设置
键:=0OnKeyDown
事件处理程序中的code>应阻止ListBox1控件处理退格键。但这不起作用,如您所见:BACKSPACE键导致选择从Item5更改为Item1:

那么,如何防止在聚焦的ListBox控件中处理退格键并更改ListBox的选择

德尔福10.1柏林更新2

Windows 7 x64 SP1

改用
OnKeyPress
事件:

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #8 then
  begin
    if ListBox1.Focused then
    begin
      Key := #0;
      CodeSite.Send('ListBox1 is focused!');
    end;
  end;
end;

您不能总是在
OnKeyDown
中阻止所有内容,请改用
OnKeyPress
事件:

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #8 then
  begin
    if ListBox1.Focused then
    begin
      Key := #0;
      CodeSite.Send('ListBox1 is focused!');
    end;
  end;
end;

OnKeyDown

阅读关于WM的内容时,您不能总是阻止所有内容_GETDLGCODE@DavidHeffernan:您建议从该消息返回什么值?没有任何标志表示忽略退格键击。您是否在考虑禁用
DLGC\u wantKeys
和/或
DLGC\u WANTCHARS
标志,或启用
DLGC\u WANTMESSAGE
标志?您必须更具体一些。TranslateMessage在消息循环中的DispatchMessage之前被调用,因此您没有阻止将WM_字符(从WM_键向下翻译)发布到列表框。因此,雷米的答案是……阅读关于WM的文章_GETDLGCODE@DavidHeffernan:您建议从该消息返回什么值?没有任何标志表示忽略退格键击。您是否在考虑禁用
DLGC\u wantKeys
和/或
DLGC\u WANTCHARS
标志,或启用
DLGC\u WANTMESSAGE
标志?您必须更具体一些。TranslateMessage在消息循环中的DispatchMessage之前被调用,因此您没有阻止将WM_字符(从WM_键向下翻译)发布到列表框。因此,雷米的回答……谢谢你,它起作用了。但这是令人惊讶的,因为
OnKeyDown
发生在
OnKeyPress
之前,尽管
Key
OnKeyDown
中显式设置为零,事件
OnKeyPress
仍然被调用!我一直相信像
BACKSPACE
这样的键不会触发
OnKeyPress
。通常,如果
OnKeyPress
拒绝一个键,则不会调用
OnKeyPress
。请注意,我的回答是使用
OnKeyPress
而不是
OnKeyDown
,而不是使用它。在任何情况下,
OnKeyDown/Up
中的
Key
是一个虚拟键代码,但是
OnKeyPress
中的
Key
是一个翻译字符,因此它们的值并不总是相同的(在这种情况下,它们是相同的)。奇怪的是,用
键:=0阻塞
HOME
键和
END
OnKeyDown
中的code>起作用,并且这些键未触发任何
OnKeyPress
事件。为什么?为什么这些键的处理方式不同?
Home
End
不是字符,根本不触发
OnKeyPress
(试试看)<代码>退格
是一个字符(Unicode代码点
U+0008
OnKeyDown/Up
被触发,以响应从键盘携带虚拟键代码的
WM\u KEYDOWN/Up
消息,即使对于非字符键也是如此,但是
OnKeyPress
在响应仅携带字符的
WM\u CHAR
时被触发:“[
WM\u CHAR
]当
TranslateMessage()
函数翻译
WM_KEYDOWN
消息时,以键盘焦点发布到窗口。
WM_CHAR
消息包含按下键的字符代码“感谢您的详细解释,非常感谢!谢谢,它很有效。但这是令人惊讶的,因为
OnKeyDown
发生在
OnKeyPress
之前,尽管
Key
OnKeyDown
中显式设置为零,事件
OnKeyPress
仍然被调用!我一直相信像
BACKSPACE
这样的键不会触发
OnKeyPress
。通常,如果
OnKeyPress
拒绝一个键,则不会调用
OnKeyPress
。请注意,我的回答是使用
OnKeyPress
而不是
OnKeyDown
,而不是使用它。在任何情况下,
OnKeyDown/Up
中的
Key
是一个虚拟键代码,但是
OnKeyPress
中的
Key
是一个翻译字符,因此它们的值并不总是相同的(在这种情况下,它们是相同的)。奇怪的是,用
键:=0阻塞
HOME
键和
END
OnKeyDown
中的code>起作用,并且这些键未触发任何
OnKeyPress
事件。为什么?为什么这些键的处理方式不同?
Home
End
不是字符,根本不触发
OnKeyPress
(试试看)<代码>退格
是一个字符(Unicode代码点
U+0008
OnKeyDown/Up
被触发,以响应从键盘携带虚拟键代码的
WM\u KEYDOWN/Up
消息,即使对于非字符键也是如此,但是
OnKeyPress
在响应仅携带字符的
WM\u CHAR
时被触发:“[
WM\u CHAR
]当
TranslateMessage()
函数翻译
WM_KEYDOWN
消息时,以键盘焦点发布到窗口。
WM_CHAR
消息包含按下键的字符代码“感谢您的详细解释,非常感谢!