Delphi VCL 应用程序,如何禁用 KeyDown 事件的默认行为?

Delphi VCL app, how to disable the default behavior of a KeyDown event?

在阅读代码时,我发现在 KeyDown 事件中可以设置 Key := 0; 以停止进一步处理该事件。例如:TIncrementalForm.FormKeyDown编码为:

procedure TIncrementalForm.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_RETURN then begin
    Key := 0; // Stop processing by input window
    if Shift = [ssShift] then
      btnPrevClick(nil)
    else
      btnNextClick(nil);
  end;
end;

另一个例子来自unit FindFrm:

procedure TFindForm.cboFindTextKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_TAB then begin
    cboFindText.SelText := #9;
    Key := 0; // prevent propagation
  end;
end;

我自己测试过,不行:

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)
    Memo1: TMemo;
    Memo2: TMemo;
    Button1: TButton;
    procedure Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private const
    VK_X = Ord('X');
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Memo1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
  if Key = VK_X then
  begin
    Key := 0;
    Memo2.Lines.Add('yes');
  end;
end;

end.

我的意图是:每当用户按下 TMemo 控件中的 x 键时,我都会执行一些业务逻辑(即在备忘录中添加“是”)并停止进一步处理。但结果是 x 键仍然插入到 TMemo 文本中。我想知道如何禁用默认按键按住事件行为(插入相应的按键)。

这里的关键(没有双关语意)是使用 OnKeyPress 而不是 OnKeyDown:

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
  if Key = 'x' then
  begin
    Key := #0;
    Memo1.Lines.Add('yes');
  end;
end;

不是答案,而是评论,但我需要发布代码,所以...

您可以使用这些函数测试当前 Shift 状态:

CONST
  VK_ALT        = VK_MENU;
  VK_CTRL       = VK_CONTROL;

FUNCTION KeyPressed(VirtualKey : WORD) : BOOLEAN;
  BEGIN
    Result:=(GetKeyState(VirtualKey) AND 000000<>0)
  END;

FUNCTION Shift : BOOLEAN;
  BEGIN
    Result:=KeyPressed(VK_SHIFT)
  END;

FUNCTION Alt : BOOLEAN;
  BEGIN
    Result:=KeyPressed(VK_ALT)
  END;

FUNCTION Ctrl : BOOLEAN;
  BEGIN
    Result:=KeyPressed(VK_CTRL)
  END;

但请注意,您必须在键盘事件的尾部和新的键盘事件发生之前调用这些函数,因为此调用将 return 与 的状态相同最新的 键盘事件,而不是在您想要的时间必须处于活动状态的事件(如果您在键盘事件处理程序之外调用它)。