这是我的程序菜单在Delphi 2009下的设计模式中的样子:
请注意,主菜单和文件子菜单中的每个单词都有一个带下划线的字母.应该是这样的.这个带下划线的字母称为加速键,是Windows应用程序的标准字母,因此您可以使用Alt键和该字母快速选择菜单项,然后使用键盘而不是鼠标快速选择子菜单项.
你通过使用“&”来获得这种方式字符作为项目标题的一部分,例如:Save& As …
当我运行我的应用程序,并使用鼠标打开文件菜单时,它看起来像这样:
并且所有Accelerator Key字母都有正确的下划线.
我玩过AutoHotKeys选项,但这不是问题.
以前有人遇到过这个问题吗?第二个图像中的示例是否是我不知道的正确行为?或者是否有一些我可能错过的选项或编码错误?
2009年11月(一年后):mghie似乎已经找到了根源,并找出了问题所在.请参阅下面接受的答案.
解决方法
[编辑]:不,不是.我刚试过,一个带有菜单项的简单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,@ShowAccel,0) then begin if ShowAccel then pDIS^.itemState := pDIS^.itemState and not ODS_NOACCEL; end; end; inherited; end;
这只是演示代码,每次收到WM_DRAWITEM消息时都不应该调用SystemParametersInfo(),而是在程序启动时调用一次,然后每次程序收到WM_SETTINGCHANGE消息时调用.