使用OnKeyDown的Delphi XE和陷印箭头键

Jef*_*non 12 windows delphi winapi delphi-xe

我希望我的表单处理箭头键,我可以这样做 - 只要表单上没有按钮.为什么是这样?

Ser*_*yuz 13

关键消息由接收这些消息的控件本身处理,这就是当您在按钮上时表单没有收到消息的原因.所以通常你必须对这些控件进行子类化,但是如果表单感兴趣的话,VCL很友好地要求父母表格做什么:

type
  TForm1 = class(TForm)
    ..
  private
    procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY;
    ..


procedure TForm1.DialogKey(var Msg: TWMKey); 
begin
  if not (Msg.CharCode in [VK_DOWN, VK_UP, VK_RIGHT, VK_LEFT]) then
    inherited;
end;
Run Code Online (Sandbox Code Playgroud)

François编辑:为了回答OP原始问题,你需要以某种方式调用onKeyDown,以便他的事件代码可以工作(随意编辑;对于评论来说太长了).

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
    { Private declarations }
    procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DialogKey(var Msg: TWMKey);
begin
  case Msg.CharCode of
    VK_DOWN, VK_UP, VK_RIGHT, VK_LEFT:
      if Assigned(onKeyDown) then
        onKeyDown(Self, Msg.CharCode, KeyDataToShiftState(Msg.KeyData));
    else
      inherited
  end;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_DOWN: Top := Top + 5;
    VK_UP: Top := Top - 5;
    VK_LEFT: Left := Left - 5;
    VK_RIGHT: Left := Left + 5;
  end;
end;
Run Code Online (Sandbox Code Playgroud)


Dav*_*nan 8

箭头键用于在表单上的按钮之间导航.这是标准的Windows行为.虽然您可以禁用此标准行为,但在违反平台标准之前应该三思.箭头键用于导航.

如果你想全面了解按键按下如何通过消息循环,我建议你阅读A Key的Odyssey.如果要在按键成为导航键之前拦截按键,则需要在IsKeyMsg之前或之前执行此操作.例如,Sertac的回答给出了一个这样的可能性.


LU *_* RD 5

只有具有焦点的对象才能接收键盘事件.

要让表单可以访问箭头键事件,请MsgHandler在表单的公共部分声明a .在表单创建构造函数中,将其分配Application.OnMessage给此MsgHandler.

下面的代码只有当它们来自TButton后代时才截获箭头键.可以根据需要添加更多控件.

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := Self.MsgHandler;
end;

procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean);
var
  ActiveControl: TWinControl;
  key : word;
begin
  if (Msg.message = WM_KEYDOWN) then
    begin
      ActiveControl := Screen.ActiveControl;
      // if the active control inherits from TButton, intercept the key.
      // add other controls as fit your needs 
      if not ActiveControl.InheritsFrom(TButton)
        then Exit;

      key := Msg.wParam;
      Handled := true;
      case Key of // intercept the wanted keys
        VK_DOWN : ; // doStuff
        VK_UP : ; // doStuff
        VK_LEFT : ; // doStuff
        VK_RIGHT : ; // doStuff
        else Handled := false;
      end;
   end;
end;
Run Code Online (Sandbox Code Playgroud)