我想在用户按下键OnKeyPress
时接收事件。Tab
procedure TForm1.Edit1(Sender: TObject; var Key: Char);
begin
case Key of
#09:
begin
//Snip - Stuff i want to do
end;
end;
end;
我尝试对Edit
框进行子类化,并处理WM_GETDLGCODE
消息:
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_GETDLGCODE: Message.Result := DLGC_WANTTAB;
else
FOldAccountNumberWindowProc(Message);
end;
end;
我现在收到Tab KeyPress事件(如我所愿),但现在按Left或Right光标键会导致焦点转移到 tab 顺序中的上一个或下一个控件。
接收 Tab Key Press事件的正确方法是什么?
奖金阅读
我尝试按照 MSDN 文档中的说明进行操作:
wParam
用户按下的虚拟键,提示 Windows 发出此通知。处理程序必须有选择地处理这些键。例如,处理程序可能接受并处理 VK_RETURN,但将 VK_TAB 委托给所有者窗口。有关值的列表,请参阅虚拟键代码。lParam指向 MSG 结构的指针(如果系统正在执行查询,则为 NULL)。
但wParam
和wParam
都为零。
更新二
我意识到我和这个答案有同样的错误:
if Message.Msg = WM_GETDLGCODE then
Message.Result:= Message.Result or DLGC_WANTTAB
else
if Assigned(FOldWndProc) then FOldWndProc(Message);
当我应该实际使用同一答案中其他地方列出的正确代码中的概念时:
if Assigned(FOldWndProc) then FOldWndProc(Message);
if Message.Msg = WM_GETDLGCODE then
Message.Result:= Message.Result or DLGC_WANTTAB;
这有助于解释为什么我的原始代码是错误的。设置Message.Result
为DLGC_WANTTAB
错误:
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_GETDLGCODE: Message.Result := DLGC_WANTTAB;
else
FOldAccountNumberWindowProc(Message);
end;
end;
尝试bitwise or
将标志DLGC_WANTTAB
放入也是错误的Message.Result
,因为Message.Result
还没有值:
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_GETDLGCODE: Message.Result := Message.Result or DLGC_WANTTAB;
else
FOldAccountNumberWindowProc(Message);
end;
end;
我必须首先调用原始窗口过程,才能让 Windows 的EDIT
控件设置正确的Message.Result
. 然后我可以按位组合DLGC_WANTTAB
:
procedure TfrmEnableVIPMode.AccountNumberWindowProc(var Message: TMessage);
begin
FOldAccountNumberWindowProc(Message);
case Message.Msg of
WM_GETDLGCODE: Message.Result := Message.Result or DLGC_WANTTAB;
end;
end;
套用 Raymond Chen 的博客条目,并根据需要添加重点:
在询问原始控件它认为它想要什么行为之后,我们打开 DLGC_WANTTAB 标志
所以这个比较好。光标键继续在编辑控件中导航文本(而不是转移焦点),并且我收到OnKeyPress
(和OnKeyDown
和OnKeyUp
)Tab键的事件。
剩下的问题是用户按下Tab不再转移焦点。
我试图开始手动修改焦点,改变自己:
procedure TfrmEnableVIPMode.edAccountNumberKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
#09:
begin
//Snip - Stuff i want to do
{
The DLGC_WANTTAB technique broke Windows focus change.
Keep throwing in hacks until it's no longer obviously broken
}
//Perform(CM_DialogKey, VK_TAB, 0); //doesn't work
Self.ActiveControl := Self.FindNextControl(edAccountNumber, True, True, False);
end;
end;
end;
上面的代码有效 - 如果用户按下Tab键。但正如 Raymond Chen 六年前指出的那样,代码被破坏了:
这种方法有很多问题。您可能会花费大量时间来挑剔小细节,此代码如何无法正确设置对话框中的焦点,如何无法将嵌套对话框考虑在内,如何无法处理 Shift+Tab 导航键
就我而言,我打破了Shift+ Tab。谁知道还有什么。
所以,我的问题:
如何在编辑框中接收 TAB 键按下?
我不想吃它们,我只想知道用户按下了Tab键。