Delphi XE2:如何防止Alt键夺取焦点?

3

当光标在编辑字段中时,按下并释放Alt键(未按下其他任何键)会导致编辑字段失去焦点。这也会发生在其他聚焦控件上。如何在Delphi程序中防止此现象发生在任何聚焦控件上?


10
不要试图修复本来就没有问题的事情。 所有Windows程序都是这样运作的。当按下Alt键时,菜单就会被激活。如果你的窗口没有主菜单,则会激活窗口菜单(通过在左上角点击图标获得)。你可以使用箭头键浏览窗口菜单以了解情况。解决方法是更好的用户教育,而不是试图改变您的程序与其他程序的行为方式。当焦点被窃取时,只需再次按下Alt键或Esc键即可取消菜单模式。 - Rob Kennedy
拦截所有窗口消息并过滤掉打开菜单的消息。但是这样做有很多机会完全破坏程序。如果你的用户不够聪明,最好为他们制作一个大横幅,当他们打开菜单时显示,这样他们就知道必须返回到输入框。 - Arioch 'The
1
@Rob Kennedy 我理解你对于Windows一致性的讲话,而且通常我也同意你的观点。然而,在某些非常特殊的情况下,防止Alt键窃取焦点可能会很有用。 同时,我已经找到了一个解决方案:在你想要避免使用Alt键失去焦点的控件的OnKeyDown事件处理程序中编写以下代码:if Shift = [ssAlt] then Key := 0; - user1580348
3
这会禁用所有的Alt+某些热键,可能一些基于AltGr的umlaut字符将无法访问。 - Arioch 'The
1
正如我所说:在“非常特殊的情况”下(不需要使用Alt +某些键)。 - user1580348
显示剩余2条评论
2个回答

5
更好的方法是采用更为精确的方式以减少不必要的影响 - 我建议您:
在表单中,覆盖WndProc:
TForm1 = class(TForm)
  Edit1: TEdit;
private
   FSuppress : boolean;
protected
   procedure WndProc(var Message : TMessage); override;
end;

像这样实现:
procedure TForm1.WndProc(var Message : TMessage);
begin
  if (Message.Msg = WM_SYSCOMMAND) and
     (Message.WParam = SC_KEYMENU) and
     FSuppress then Exit;

  inherited WndProc(Message);
end;

这是一个系统命令的Windows消息,特定的WParam表明它是用于检索由按键触发的菜单。在您希望保持焦点的任何控件上设置FSuppress

procedure TForm1.Edit1Enter(Sender: TObject);
begin
  FSuppress := true;
end;

procedure TForm1.Edit1Exit(Sender: TObject);
begin
  FSuppress := false;
end;

这不会禁用 ALT 键,但会具体禁用当 Edit1 获得焦点时激活菜单。重要的是,像 ALT + F4 退出程序或 ALT+TAB 切换窗口这样的快捷键仍然有效。
我同意大多数评论,但这可能不是您用户群的最佳解决方案。您实质上正在削弱有能力的用户,以迎合无能的用户。也许可以像 Windows 粘滞键或各种残障人士的辅助选项一样将其作为选项。

仅供参考,您建议定义的两个常量已经在 Windows.pas 中定义,并且至少从 Delphi 2 开始就一直存在。由于这是一个 VCL 表单的单元,因此 Windows 已经在 uses 子句中,而声明是多余的。 - Ken White
@KenWhite 我也是这么想的... 错误提示说它们未知,所以我只是添加了它们。有时候我觉得错误提示需要给自己加下划线。 - J...
谢谢,这是一个完美的解决方案。就像我之前说的:这是为了一个非常特殊的情况。当然,我已经改变了变量名。 - user1580348

0
procedure SendKey_ALT;
begin
    keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0);
    keybd_event(VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0);
end;

在你的FormCreate()方法中调用上述过程,这将解决问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接