当焦点控件干扰时如何捕获 KeyDown?

问题描述

我有一个 KeyPreview=true 的表单并且想要捕获箭头键,除非我们在一个应该处理这些的控件中。 问题是:重点始终放在这些控件之一上。

我如何调整/设计它以使其工作?

.PAS 文件

unit uKeyDownTests;

interface

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

type
  TFrmKeyDownTests = class(TForm)
    PnlBottom: TPanel;
    PnlClient: TPanel;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
  public
  end;

var
  FrmKeyDownTests: TFrmKeyDownTests;

implementation

{$R *.dfm}

type
  THackWinControl = class(TWinControl);

procedure TFrmKeyDownTests.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var lActiveControl: TControl;
begin
   // Earlier code,but that did not work either:
   // if Edit1.Focused or Edit2.Focused or Edit3.Focused then Exit;

   lActiveControl := ActiveControl;
   if Assigned(lActiveControl) then
   begin
      if lActiveControl = Edit1 then
      begin
          THackWinControl(Edit1).KeyDown(Key,Shift);
          Exit;
      end;
      if lActiveControl = Edit2 then
      begin
          THackWinControl(Edit2).KeyDown(Key,Shift);
          Exit;
      end;
      if lActiveControl = Edit3 then
      begin
          THackWinControl(Edit3).KeyDown(Key,Shift);
          Exit;
      end;
   end;

   if (Key = VK_RIGHT) then
   begin
      PnlBottom.Caption := PnlBottom.Caption + 'R';
      Key := 0;
      Exit;
   end;
   if (Key = VK_LEFT) then
   begin
      PnlBottom.Caption := PnlBottom.Caption + 'L';
      Key := 0;
      Exit;
   end;
   if (Key = VK_UP) then
   begin
      PnlBottom.Caption := PnlBottom.Caption + 'U';
      Key := 0;
      Exit;
   end;
   if (Key = VK_DOWN) then
   begin
      PnlBottom.Caption := PnlBottom.Caption + 'D';
      Key := 0;
      Exit;
   end;
end;

end.

.DFM 文件

object FrmKeyDownTests: TFrmKeyDownTests
  Left = 0
  Top = 0
  Caption = 'Keydown tests'
  ClientHeight = 336
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  KeyPreview = True
  OldCreateOrder = False
  OnKeyDown = FormKeyDown
  PixelsPerInch = 96
  TextHeight = 13
  object PnlBottom: TPanel
    Left = 0
    Top = 295
    Width = 635
    Height = 41
    Align = alBottom
    TabOrder = 0
  end
  object PnlClient: TPanel
    Left = 0
    Top = 0
    Width = 635
    Height = 295
    Align = alClient
    TabOrder = 1
    object Edit1: TEdit
      Left = 40
      Top = 32
      Width = 121
      Height = 21
      TabOrder = 0
      Text = 'Edit1'
    end
    object Edit2: TEdit
      Left = 40
      Top = 72
      Width = 121
      Height = 21
      TabOrder = 1
      Text = 'Edit1'
    end
    object Edit3: TEdit
      Left = 40
      Top = 112
      Width = 121
      Height = 21
      TabOrder = 2
      Text = 'Edit1'
    end
  end
end

解决方法

针对我的具体情况回答我自己的问题,与“可能的欺骗”中的问题略有不同,但基于那里的答案
就我而言,最简单的解决方案是:

  • procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY; only 调用继承的
  • KeyPreview=true 用于表单
  • 一个 FormKeydown 处理我想用箭头键做的事情

结果:

  • 具有焦点的控件以及表单处理箭头键
  • 控件是否具有 OnKeyDown 处理程序(Edit2 控件)或没有(其他控件)并不重要

修改后的代码:

unit uKeyDownTests;

interface

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

type
  TFrmKeyDownTests = class(TForm)
    PnlBottom: TPanel;
    PnlClient: TPanel;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure Edit2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
    procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY;  public
  end;

var
  FrmKeyDownTests: TFrmKeyDownTests;

implementation

{$R *.dfm}

procedure TFrmKeyDownTests.DialogKey(var Msg: TWMKey);
begin
   inherited;
end;

procedure TFrmKeyDownTests.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
   case Key of
      VK_RIGHT: PnlBottom.Caption := PnlBottom.Caption + 'R';
      VK_LEFT : PnlBottom.Caption := PnlBottom.Caption + 'L';
      VK_UP   : PnlBottom.Caption := PnlBottom.Caption + 'U';
      VK_DOWN : PnlBottom.Caption := PnlBottom.Caption + 'D';
   end;
end;


{ TFrmKeyDownTests }

procedure TFrmKeyDownTests.Edit2KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
   PnlBottom.Caption := PnlBottom.Caption + '-kd-';
end;

end.

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...