ShortCut 什么时候触发? [英] When does a ShortCut fire?

查看:21
本文介绍了ShortCut 什么时候触发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

昨天我发现了一种情况,即键盘快捷键没有按预期触发.

Yesterday I discovered a situation wherein a keyboard ShortCut did not fire when I was expecting it to.

具体情况是:我在 MDI 子项上按下了 ActionList 的一个 Action 的 ShortCut 组合键,而 MDI 表单上的侧边栏被聚焦.

The specific situation was: I pressed the ShortCut key combination for an Action of an ActionList on an MDI child, while a side bar on the MDI form was focussed.

我一直认为 ShortCuts 可以在全球范围内使用.他们究竟在哪些情况下会开火或不会开火?

I always was under the impression that ShortCuts would work globally. In exactly which circumstances do or do they not fire?

推荐答案

这是一个看似简单的问题,但答案却出奇的长.首先,我将处理一些基础知识,然后通过 VCL 代码按照 ShortCut 进行操作,最终得出 - 我希望 - 一个令人满意的结论.

That's a deceptively simple question with a surprisingly long answer. First I will deal with some basics and then follow the ShortCut through the VCL code to finally arrive at - I hope - a satisfying conclusion.

ShortCut 表示一个或多个引起操作的键的特殊键盘组合.Special 对赋予特定组合键意义的程序员来说是特殊的.

A ShortCut represents a special keyboard combination of one or more keys that cause an operation. Special means special to the programmer who gives meaning to the specific key combination.

在 Delphi 中,快捷方式的类型为 TShortCut,它被声明为 Word 范围 (0..65535) 内的整数.ShortCut 通常由几个键构成,例如:

In Delphi a ShortCut is of type TShortCut which is declared as a whole number within the Word range (0..65535). A ShortCut is often constructed out of several keys, e.g.:

CTRL+K = scCtrl + Ord('K') = 16384 + 75 = 16459.

CTRL+K = scCtrl + Ord('K') = 16384 + 75 = 16459.

ShortCuts 可以分配给 Action 的 ShortCutSecondaryShortCuts 属性,或者分配给 MenuItem 的 ShortCut 属性,从而调用该 Action 的OnExecute 事件或 MenuItem 的 OnClick 事件,当 ShortCut 的键盘组合被按下时.

ShortCuts can be assigned to the ShortCut or SecondaryShortCuts property of an Action or to the ShortCut property of a MenuItem, thus invoking that Action's OnExecute event or MenuItem's OnClick event when the ShortCut's keyboard combination is pressed.

要处理Action 的ShortCut,需要启用Action,并添加到未挂起的ActionList 或附加到启用的MenuItem.同样,要处理MenuItem的ShortCut,需要将MenuItem添加到Menu中.

For an Action's ShortCut to be processed, it is required that the Action is enabled, and added to a not suspended ActionList or attached to an enabled MenuItem. Likewise, for a MenuItem's ShortCut to be processed, it is required that the MenuItem is added to a Menu.

ShortCuts 也可以从 应用程序解释的、表单或来自ApplicationEvents' OnShortCut 事件.在这些事件中,Msg 参数在其 CharCode 成员中保存键码,以及可能的特殊键,如 ShiftCtrlAlt 可以使用 GetKeyState:

ShortCuts can also be interpreted from the Application's, a Form's or from an ApplicationEvents' OnShortCut event. Within those events, the Msg parameter holds the keycode in its CharCode member, and possibly special keys like Shift, Ctrl or Alt can be extracted using GetKeyState:

procedure TForm1.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  if (Msg.CharCode = Ord('K')) and (GetKeyState(VK_CONTROL) < 0) then
  begin
    Caption := 'CTRL+K pressed';
    Handled := True;
  end;
end;

如果 Handled 参数设置为 True,将跳过对该键的任何后续处理.

If the Handled parameter is set to True, any subsequent processing for the key will be skipped.

VCL 不会保留所有指定快捷方式的列表.(怎么可能?).因此,所有 击键都可能是快捷方式.这正是 VCL 解释 ShortCuts 的方式:通过评估每个按下的键.

The VCL does not keep a list of all specified ShortCuts. (How could it?). Thus all keystrokes could potentially be a ShortCut. And that is exactly how the VCL interprets ShortCuts: by evaluating every key that is pressed.

Peter Above 通过 VCL 撰写了一篇出色而全面的文章,内容涉及A Key's Odyssey.简而言之,ShortCut 被捕获如下:

Peter Below wrote an excellent and comprehensive article dealing with A Key's Odyssey through the VCL. In short, a ShortCut is catched as follows:

  • TApplication.Run 获取发送到应用程序的每条 Windows 消息,
  • TApplication.ProcessMessage 调用 IsKeyMsg,后者将消息(如果是 WM_KEYDOWN 消息)传递到 CN_KEYDOWN焦点控件的消息处理程序.
  • TApplication.Run picks up every Windows message send to the application,
  • TApplication.ProcessMessage calls IsKeyMsg which passes the message - if a WM_KEYDOWN message - on to the CN_KEYDOWN message handler of the focussed Control.

TWinControl.CNKeyDown 检查键是否是菜单键(我们将看到这个menu 的定义超出了物理菜单):

TWinControl.CNKeyDown examines whether the key is a menu key (we'll see the definition of this menu is beyond a physical Menu):

  • TWinControl.IsMenuKey 首先检查键是否为控件或其父级 PopupMenu 中的一个快捷方式,
    • TMenu.IsShortCut 1) 遍历所有其(子)菜单项,并使用 ShortCut(如果有)调用已启用 MenuItem 的 OnClick 事件处理程序,
    • TWinControl.IsMenuKey first examines whether the key is a ShortCut within the Control's or one of its parent's PopupMenu,
      • TMenu.IsShortCut 1) traverses all its (sub)menu items and calls the OnClick event handler of the enabled MenuItem with the ShortCut, if any,
      • OnShortCut 窗体的事件 被调用,如果已分配,
      • 如果未处理,则检查该键是否为 Form 的 MainMenu 中的 ShortCut(参见 1)),如果有,
      • 如果未处理,它会将键分派给 Form 拥有的所有 ActionList(仍在讨论活动 Form).在 Delphi 版本 10 (BDS2006) 之前,这些 ActionList 需要由 Form 直接拥有并保存在受保护的(在需要时可以进行干预)字段 FActionLists 中.这被认为是一个错误,从 BDS2006 开始,该领域被淘汰,ActionLists 也可以由 Form 间接拥有.
        • TCustomActionList.IsShortCut 遍历其所有 Action 并调用已启用 Action 的 HandleShortCut,并使用在其 ShortCutSecondaryShortCuts 属性中设置的 ShortCut,莉>
        • The OnShortCut event of the Form is called, if assigned,
        • If not processed, it examines whether the key is a ShortCut within the Form's MainMenu (see 1)), if any,
        • If not processed, it dispatches the key to all ActionLists owned by the Form (still talking about the active Form). Prior to Delphi version 10 (BDS2006), these ActionLists need to be directly owned by the Form and were kept in a protected (which made intervention possible when needed) field FActionLists. That was considered a bug and as from BDS2006, the field was eliminated and the ActionLists could be indirectly owned by the Form too.
          • TCustomActionList.IsShortCut traverses all its Actions and calls HandleShortCut of the enabled Action with the ShortCut set in its ShortCut or SecondaryShortCuts property, if any,
          • OnShortCut 应用程序事件 被触发,这包括 OnShortCut 项目中所有 ApplicationEvents 组件的事件,如果有分配的话,
          • 如果没有被处理,它会调用MainFormIsShortCut例程(见2)),但仅当MainForm已启用.例如.当活动表单是模态表单时,MainForm 将被禁用.这将触发 MainForm 的 OnShortCut 事件 或遍历所有直接或间接拥有的 MainForm 的ActionLists(取决于上面提到的 Delphi 版本).
          • The OnShortCut event of the Application is fired, this includes OnShortCut events of all ApplicationEvents components within the project, if any assigned,
          • If not processed, it calls the IsShortCut routine of the MainForm (see 2)), but only when the MainForm is enabled. E.g. when the active Form is a modal Form, then the MainForm will be disabled. This will fire the OnShortCut event of the MainForm or will traverse all directly or indirectly owned ActionLists of the MainForm (depending on Delphi version as mentioned above).

          什么时候:

          • 在附加到当前焦点控件或其任何父级的 PopupMenu 中设置启用的 MenuItem,
          • 在 MainMenu 中设置已启用的 MenuItem,该菜单项显示在当前活动的 Form 或 MainForm 上,但仅在启用 MainForm 时,
          • 在当前活动的 Form 或 MainForm 拥有的未挂起的 ActionList 中为启用的 Action 设置,但仅当启用 MainForm 时,
          • 在当前活动 Form 或 MainForm 的 OnShortCut 事件中捕获,但仅在启用 MainForm 时,
          • 在应用程序或任何 ApplicationEvents 组件的 OnShortCut 事件中捕获.
          • Set for an enabled MenuItem in a PopupMenu which is attached to the currently focussed Control or to any of its parents,
          • Set for an enabled MenuItem in a MainMenu which is shown on the currently active Form or on the MainForm, but only when the MainForm is enabled,
          • Set for an enabled Action in a not suspended ActionList which is owned by the currently active Form or by the MainForm, but only when the MainForm is enabled,
          • Catched in the OnShortCut event of the currently active Form or of the MainForm, but only when the MainForm is enabled,
          • Catched in the OnShortCut event of the Applicaton or any ApplicationEvents components.

          设置为:

          • 禁用的 MenuItem,
          • 没有菜单的 MenuItem,
          • MainMenu 中未附加到表单的 MenuItem,
          • PopupMenu 中的一个 MenuItem 附加到同级,
          • 禁用的操作,
          • 没有 ActionList 的 Action,
          • ActionList 中不属于当前活动 Form 或 MainForm 的 Action.例如:另一个表单、数据模块、应用程序、实用程序单元等...
          • BDS2006 以下 Delphi 版本中,ActionList 中不直接由当前活动的 Form 或 MainForm 拥有的 Action.

          这篇关于ShortCut 什么时候触发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆