The arrow keys do not trigger the OnKeyDown and OnKeyUp events

Problem The OnKeyDown event works well with component XY. However the arrow keys do not trigger this event.
Solution The problem of not getting fired the OnKeyDown event by the arrow keys is due to the top message loop which intercepts the arrow keys and diverts the corresponding message to perform navigation on the form. So the solution is quite simple: write your own message handler which prevents the navigation keys to be processed by the VCL message loop.

The following code shows how to make the arrow and tab keys fire the OnKeyDown/OnKeyUp events for a TPlot3D component. The form (instance Form1) contains a TPlot3D component (instance PL1), the OnShow event of the form is used to set the focus to the PL1 component. The message handler code is displayed in red color.

unit Unit43;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
  Vcl.Dialogs, SDL_plot3d, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    PL1: TPlot3D;
    Label1: TLabel;
    Label2: TLabel;
    procedure FormShow(Sender: TObject);
    procedure PL1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure PL1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
         // message handler for the navigation keys
    procedure CMDialogKey(var Message: TCMDialogKey); message CM_DIALOGKEY;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.CMDialogKey(var Message: TCMDialogKey);

begin
   // suppress the standard processing for the arrow and tab keys
if (Message.CharCode <> VK_LEFT) and
   (Message.CharCode <> VK_RIGHT) and
   (Message.CharCode <> VK_DOWN) and
   (Message.CharCode <> VK_UP) and
   (Message.CharCode <> VK_TAB) then
  inherited;
end;

procedure TForm1.FormShow(Sender: TObject);

begin
PL1.SetFocus;
end;

procedure TForm1.PL1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);

begin
Label1.Caption := 'key down: '+IntToStr(Key);
Label2.Caption := '';
end;

procedure TForm1.PL1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);

begin
Label2.Caption := 'key up';
Label1.Caption := '';
end;

end.

Hint: Peter Below wrote an excellent article on the processing of key messages which is available in the Embarcadero Developer Network.

 


Last Update: 2014-10-10