【问题标题】:Menu Accelerator Keys Not Showing Up (Delphi 2009)菜单加速键未显示 (Delphi 2009)
【发布时间】:2010-09-21 18:27:48
【问题描述】:

我已经尽力了,但无法弄清楚这里发生了什么。它在 Delphi 4 中运行良好。升级到 Delphi 2009 后,我不知道这是它应该工作的方式,还是有问题:

这是我的程序菜单在 Delphi 2009 下的设计模式下的样子:

请注意,主菜单和文件子菜单中的每个单词都有一个字母加下划线。它应该是这样的。这个带下划线的字母称为加速键,是 Windows 应用程序中的标准,因此您可以使用 Alt 键和该字母快速选择菜单项,然后用键盘而不是鼠标选择子菜单项。

您可以通过使用“&”字符作为项目标题的一部分来获取它们,例如:Save &As...

当我运行我的应用程序并使用鼠标打开文件菜单时,它看起来像这样:

字符在主菜单中有下划线,但在文件菜单中没有下划线。

如果相反,我使用 Alt-F 键打开文件子菜单,那么它看起来是这样的:

并且所有加速键字母都带有适当的下划线。

我玩过 AutoHotKeys 选项,但这不是问题。

以前有人遇到过这个问题吗?第二张图片中的示例是我不知道的正确行为吗?或者是否有一些我可能遗漏的选项或编码错误?


2009 年 11 月(一年后):mghie 似乎已经找到了问题的根源并找出了问题所在。请参阅下面他接受的答案。

【问题讨论】:

    标签: delphi menu delphi-2009 acceleratorkey


    【解决方案1】:

    有一个标准的 Windows 设置(在显示属性下)通常隐藏这些加速器,除非按住 Alt 键。这可以解释为什么使用 Alt+F10 打开菜单会为您显示它们。可能是这个原因?

    [编辑]:不,不是。我刚刚尝试过,一个带有菜单项的简单 TForm 显示了加速器,但是只要我添加一个 TImageList 并设置单个菜单项的 ImageIndex,或者简单地将 OwnerDraw 设置为 true,那么加速器下划线就会消失。我想这确实是 VCL 中的一个错误。

    顺便说一句,这是在 Windows XP 上。

    解决方法:

    我在 Windows XP 64 上使用 Delphi 2009 对此进行了调试,缺少加速器的根本原因似乎是 Windows 发送带有 ODS_NOACCEL 标志集的 WM_DRAWITEM 消息,如果系统是设置为始终显示加速器。所以你可以说这不是 VCL 错误,而是 VCL 无法解决的 Windows 问题。

    但是,您可以在自己的代码中解决它,您只需在将消息传递给 VCL 之前重置标志。覆盖窗口进程

    protected
      procedure WndProc(var Message: TMessage); override;
    

    像这样:

    procedure TYourForm.WndProc(var Message: TMessage);
    const
      ODS_NOACCEL = $100;
    var
      pDIS: PDrawItemStruct;
      ShowAccel: BOOL;
    begin
      if (Message.Msg = WM_DRAWITEM) then begin
        pDIS := PDrawItemStruct(Message.LParam);
        if (pDIS^.CtlType = ODT_MENU)
          and SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, @ShowAccel, 0)
        then begin
          if ShowAccel then
            pDIS^.itemState := pDIS^.itemState and not ODS_NOACCEL;
        end;
      end;
      inherited;
    end;
    

    这只是演示代码,你不应该在每次收到WM_DRAWITEM消息时调用SystemParametersInfo(),而是在程序启动时调用一次,然后每次你的程序收到WM_SETTINGCHANGE消息。

    【讨论】:

    • 我也在使用 Windows XP。在这些答案和我对此的思考以及您的帮助之后,我同意这可能是 VCL 中的一个错误。我会报告的。
    • 顺便说一句,我在 Delphi 2007 上得到了相同的行为。
    • Mghie:感谢您对此事的进一步研究(一年后!!)并找到了这一点。我已经用你的信息更新了 Embarcadero 的错误报告。希望我能给你++++++++++1
    • 在程序启动时调用 SystemParametersInfo() 99% 的时间就足够了。
    • 受您的代码启发,我想强制 TPopupMenu 始终显示下划线,所以在WndProc 中我总是调用pDIS^.itemState := pDIS^.itemState and not ODS_NOACCEL; 以确保ODS_NOACCEL 标志被排除,但不幸的是它不起作用。有什么提示吗?谢谢。
    【解决方案2】:

    这是 Windows 2000 引入的“功能”:

    新旧事物:Why does Windows hide keyboard accelerators and focus rectangles by default?

    Delphi 4 似乎不支持此 Windows 功能。

    要让 2000 和 XP 菜单显示加速键,右键单击桌面上的空白处,选择属性,单击外观选项卡,然后在效果下,取消选中 隐藏键盘导航的下划线字母,直到我按下 Alt键。单击确定两次。

    不知道如何在 Vista 中做到这一点。

    【讨论】:

    • 我以为你有答案。但不幸的是,当我查看“隐藏带下划线的字母”选项时(我以前从不知道它),我发现它没有被选中。
    • 什么操作系统?您的屏幕截图看起来像 XP。我刚刚在 XP 上尝试过,它可以工作(取消选中该选项并显示加速键下划线。)也许你需要重新启动。
    【解决方案3】:

    我认为这不是 Delphi 生成的错误,因为您在 Vista 上使用记事本有相同的行为。顺便说一句,德尔福本身也在...
    我必须承认在你的问题之前我没有注意。感谢您指出。

    【讨论】:

    • 没有。在我的 Delphi 2009 中,所有子菜单项都显示加速键,即使我用鼠标选择菜单也是如此。这就是为什么我认为这是我拥有的一些设置,而不是 Delphi 或操作系统。这绝对是一个奇怪的问题,我已经花了大约 4 个小时试图修复它。
    【解决方案4】:

    正如 Jim McKeeth 上面指出的(正确地),这是“设计使然”的行为。如果菜单是通过键盘操作触发的,则应显示加速器,但如果由鼠标触发,则有意不显示加速器。

    我已将 XP 配置为始终显示加速器,但更改该选项的快速测试确认菜单也不应显示下划线(Visual Studio 响应如我预期,使用鼠标时没有下划线)。但是,Microsoft Office 会忽略此设置并始终显示下划线。所以它看起来像是在 Delphi 中如何绘制菜单的一个错误(我自己对 Delphi 没有任何经验)。

    我也找到了 Vista 的选项:http://www.vistax64.com/vista-general/42125-always-show-menu-underline-keyboard-accelerators.html

    您可以在新的“轻松访问中心”中启用此功能(转到“控制” 面板,单击轻松访问,然后单击轻松访问中心)。在 轻松访问中心,单击使键盘更易于使用,然后 在最底部选择下划线键盘快捷键并访问 键复选框。

    在做进一步研究时,我在 Delphi 论坛上发现了这个相关的错误:http://qc.codegear.com/wc/qcmain.aspx?d=37403

    在您的情况下,子窗口(绘制的菜单)看起来没有或没有处理来自其父窗口的 WM_UIUPDATESTATE 消息,这就是导致使用加速器重绘的原因。

    【讨论】:

    • “在您的情况下,看起来子窗口(绘制的菜单)没有收到或没有处理来自其父窗口的 WM_UIUPDATESTATE 消息,这就是导致使用加速器重绘的原因” - 完全正确!那是虫子!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多