二级表格上的德尔福TActionMainMenu加速器

时间:2016-06-07 22:36:49

标签: delphi

我正在使用Windows 10中的Delphi XE7。我在主要表单和模态辅助表单上都有一个TMainMenuBar。问题是,如果辅助表单还包含TMemo,则辅助表单上的加速键不会激活菜单。例如,如果辅助表单具有“文件”菜单,则Alt + F不会打开文件菜单。但是,如果按下并释放alt,则“文件”突出显示,“F”加下划线,按F将打开菜单。请注意,如果删除TMemo,问题将消失。此外,主窗体上的Tmemo不会导致主窗体上的菜单出现问题。

我搜索了“辅助表单上的TActionMainMenuBar加速键”,但没有一个匹配描述这个特定问题,尽管讨论了此组件和加速键的其他问题。有没有人知道如何在两个表单上使用TActionMainMenuBar时实现所需的行为? (出于各种原因,我宁愿不使用标准的TMenu。)

1 个答案:

答案 0 :(得分:5)

这是一个VCL设计问题。 (下面的解释可能有点偏离。我正在跟踪XE2并且行为不完全相同。您可能需要在解决方案部分留下一个消息处理程序。)

菜单栏加速器会生成WM_SYSCOMMAND条消息。您的确切加速器案例在API documentation中作为示例提供:

  

如果wParam是 SC_KEYMENU ,则lParam包含的字符代码   与ALT键一起使用的键,用于显示弹出菜单。对于   例如,按ALT + F显示File弹出窗口将导致a    WM_SYSCOMMAND ,wParam等于 SC_KEYMENU ,lParam等于'f'。

操作菜单栏是专有的VCL组件。因此,表单的默认窗口过程没有机会为它们处理加速器消息。组件本身具有模拟行为的代码(TCustomActionMainMenuBar.WMSysCommand),但必须传递消息才能执行此操作。 VCL的设计问题是,只有主表单上的动作菜单栏才有机会。

TWinControl收到WM_SYSCOMMAND(辅助表单本身或本例中的备忘录),使其父表单(辅助表单)执行CM_APPSYSCOMMAND。收到消息后,表单(再次是辅助表单)将消息发送到“应用程序”窗口。应用程序的CM_APPSYSCOMMAND处理程序再次将消息转换为WM_SYSCOMMAND并将其发送到主表单。

我只能猜测,但这个设计的目的可以是,能够从没有菜单栏的辅助表格访问主菜单。

在任何情况下,如果没有切换到本机菜单,您必须拦截并将消息转发到辅助表单上的操作菜单栏,然后​​VCL处理该消息。可以有其他方法来实现这一点,但我尝试并且似乎工作的是:

type
  TSecondaryForm = class(TForm)
    ...
  protected
    procedure CMAppsyscommand(var Message: TMessage); message CM_APPSYSCOMMAND;
    procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
    ...


procedure TSecondaryForm.CMAppsyscommand(var Message: TMessage);
begin
  if ActionMainMenuBar1.Perform(PMessage(Message.LParam).Msg,,
      PMessage(Message.LParam).WParam, PMessage(Message.LParam).LParam) = 0 then
    inherited;
end;

// you may not need the below handler
procedure TSecondaryForm.WMSysCommand(var Message: TWMSysCommand);
begin
  if ActionMainMenuBar1.Perform(Message.Msg,
      TMessage(Message).WParam, TMessage(Message).LParam) = 0 then
    inherited;
end;