当表单没有焦点时,如何防止表单处理热键?

Posted

技术标签:

【中文标题】当表单没有焦点时,如何防止表单处理热键?【英文标题】:How to I keep forms from handling hotkeys when they don't have the focus? 【发布时间】:2013-03-20 03:05:08 【问题描述】:

我们有一个 Delphi XE2 应用程序。 Form1 有热键 Ctrl+FForm2 是活动的,没有热键。用户在Form2 上按Ctrl+FForm1 处理热键。这是完全不正确的,因为我们看到了非活动形式的活动。我该如何解决?

【问题讨论】:

Form1 是 MainForm 对吧?这就是重点 你有两个无模式表单,对吧?这就是 Windows 键盘加速器的工作原理。 Form1 和 Form2 不是主窗体。 我只想让热键只在活动表单上工作。我们的客户也是如此。 【参考方案1】:

我使用动作来实现所有快捷键处理。如果您这样做,那么您可以使用操作、操作列表、操作管理器等提供的集中化功能,根据表单是否处于活动状态来启用和禁用所有操作。

例如,通过在表单的OnActivateOnDeactivate 事件处理程序上设置操作列表的State 属性来做到这一点:

procedure TMyForm.FormActivate(Sender: TObject);
begin
  ActionList.State := asNormal;
end;

procedure TMyForm.FormDeactivate(Sender: TObject);
begin
  ActionList.State := asSuspended;
end;

【讨论】:

如果您的 MyForm 中有其他表单,这将无法正常工作。然后 MyForm 可能会在它仍然具有焦点时被停用。 所以我宁愿推荐一个 WM_ACTIVATE 处理程序: if msg.wParam = WA_INACTIVE then actionList.state := asSuspended else actionList.state := asNormal;【参考方案2】:

您可以在热键处理程序中添加对active form 的检查,即

if(Screen.ActiveForm <> Self)then Exit;

这是假设事件处理程序由Form1 实现(即Self 然后在处理程序内部)。

【讨论】:

【参考方案3】:

只需覆盖捕获动作的非活动窗口的以下函数:

function IsShortCut(var Message: TWMKey): Boolean; override;

function TMainForm.IsShortCut(var Message: TWMKey): Boolean;

begin
  if MainForm.Active then
    result := inherited IsShortCut( Message )
  else
    result := false;
end;

【讨论】:

以上是关于当表单没有焦点时,如何防止表单处理热键?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止热键 ` 被添加到 html 表单输入中?

非焦点表单上的 C#/WPF 热键(如 launchy)

事件处理

JavaScript / DOM:如果焦点丢失到另一个窗口(应用程序),如何防止模糊事件

防止用户在后台处理时单击表单上的任何内容的最佳方法是啥? [关闭]

当initialValues通过\绑定到props.object时,如何使用Formik表单将焦点设置在TextField\input上?