1

我有一个 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
4

1 回答 1

1

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

  • procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY;调用继承
  • 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.
于 2021-05-21T12:40:15.687 回答