Home > Software design >  Delphi VCL app, how to disable the default behavior of a KeyDown event?
Delphi VCL app, how to disable the default behavior of a KeyDown event?

Time:01-20

While I was reading code, I found that in the KeyDown event you can set Key := 0; to stop processing the event any further. For example: TIncrementalForm.FormKeyDown is coded as:

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;

Another example is from 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;

I tested it myself, but it doesn't work:

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.

My intention is: whenever the user holds down the key x in the TMemo control I do some business logic (i.e. add "yes" to the memo) and stop further processing. But the result is that the key x is still inserted to the TMemo text. I want to know how to disable the default key holding down event behavior (inserting the corresponding key).

CodePudding user response:

The key here (no pun intended) is to use OnKeyPress instead of OnKeyDown:

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

CodePudding user response:

Not an answer, but a comment, but I need to publish code, so...

You can test the current Shift-state using these functions:

CONST
  VK_ALT        = VK_MENU;
  VK_CTRL       = VK_CONTROL;

FUNCTION KeyPressed(VirtualKey : WORD) : BOOLEAN;
  BEGIN
    Result:=(GetKeyState(VirtualKey) AND $80000000<>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;

But beware that you must call these function at the tail end of a keyboard event and before a new keyboard event occurs, as this call will return the state as it was from the latest keyboard event and not the one that necessarily were active at the time you want (if you call it outside the keyboard event handler).

  •  Tags:  
  • Related