gpt4 book ai didi

windows - 将键盘事件从一个 Windows 控件转发到另一个

转载 作者:可可西里 更新时间:2023-11-01 13:29:31 25 4
gpt4 key购买 nike

在 Delphi XE 中,我正在尝试实现“即时搜索”功能 - 有点类似于 Firefox 的“键入时搜索”功能,但开源剪贴板扩展程序中的类似功能可以更好地说明 Ditto :

Ditto search interface

有一个处理典型导航事件的项目列表。但是,任何字母数字键以及导航和编辑命令(右/左箭头、shift+箭头、退格键、删除等)都应重新路由到列表下方的编辑框。编辑框的 OnChange 事件将触发列表的刷新。

UI 的要点是用户不必在控件之间使用 Tab 键或 Shift-Tab 键。这两个控件(列表和编辑框)应该“感觉”好像它们是一个单独的控件。搜索 UI 的行为应该取决于哪个控件具有焦点。

看来我最好的选择是从列表控件(我正在使用 TcxTreeList )转发某些键盘事件到编辑框,并从编辑框转发一些导航键到列表中。我怎样才能做到这一点?

注释:

  1. TcxTreeList 当然支持增量搜索,但这不是我所追求的。搜索转到 SQLite 数据库并查找子字符串匹配项。该列表仅显示数据库中的匹配项。

  2. 有一些重叠,例如这两个控件通常会处理 VK_HOME 和 VK_END,但这没关系 - 在这种情况下,键将进入列表。我需要决定是转发每个单独的按键,还是在接收它的控件中处理它。

编辑时:一种明显的方法似乎是调用编辑控件的相应 KeyDown、KeyUp 和 KeyPress 方法,如下所示:

type
THackEdit = class( TEdit );

procedure TMainForm.cxTreeList1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
THackEdit( edit1 ).KeyDown( Key, Shift );
end;

不幸的是,这没有效果。我的猜测是 TEdit 不会处理关键事件,除非它被聚焦。使用 SendMessage( THackEdit( edit1 ).Handle, WM_KEYDOWN, Key, 0 ) 也没有效果。

最佳答案

您可以使用 VCL 控件的消息处理功能并将相关消息发送给彼此。我不知道“TcxTreeList”,但下面演示了编辑控件和备忘录控件同步响应键盘事件的想法(当然只要可能)。

type
TEdit = class(stdctrls.TEdit)
private
FMsgCtrl: TWinControl;
FRecursing: Boolean;
procedure WmChar(var Msg: TWMChar); message WM_CHAR;
procedure WmKeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN;
procedure WmKeyUp(var Msg: TWMKeyUp); message WM_KEYUP;
end;

TMemo = class(stdctrls.TMemo)
private
FMsgCtrl: TWinControl;
FRecursing: Boolean;
procedure WmChar(var Msg: TWMChar); message WM_CHAR;
procedure WmKeyDown(var Msg: TWMKeyDown); message WM_KEYDOWN;
procedure WmKeyUp(var Msg: TWMKeyUp); message WM_KEYUP;
end;

TForm1 = class(TForm)
Edit1: TEdit;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
public
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

{ TEdit }

procedure TEdit.WmChar(var Msg: TWMChar);
begin
if not FRecursing then begin
inherited;

// Insert test here to see if the message will be forwarded
// exit/modify accordingly.

if Assigned(FMsgCtrl) then begin
FRecursing := True;
try
FMsgCtrl.Perform(Msg.Msg,
MakeWParam(Msg.CharCode, Msg.Unused), Msg.KeyData);
finally
FRecursing := False;
end;
end;
end;
end;

procedure TEdit.WmKeyDown(var Msg: TWMKeyDown);
begin
// exact same contents as in the above procedure
end;

procedure TEdit.WmKeyUp(var Msg: TWMKeyUp);
begin
// same here
end;

{ TMemo }

procedure TMemo.WmChar(var Msg: TWMChar);
begin
// same here
end;

procedure TMemo.WmKeyDown(var Msg: TWMKeyDown);
begin
// same here
end;

procedure TMemo.WmKeyUp(var Msg: TWMKeyUp);
begin
// same here
end;


{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.FMsgCtrl := Memo1;
Memo1.FMsgCtrl := Edit1;
end;

您可能需要干预其他消息,但您明白了。

如果出于某种原因您无法派生新控件或覆盖消息处理,则可以考虑对控件进行子类化。回答this question将向您展示如何做到这一点。

关于windows - 将键盘事件从一个 Windows 控件转发到另一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4725634/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com