当聚焦控件发生干扰时,如何捕获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;调用继承
  • 表单的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.

最新更新