有一个标准的Windows设置(在显示属性下)可以通常隐藏这些加速键,除非按住Alt键。这可能解释了为什么使用Alt + F10打开菜单会显示它们。也许这就是原因?
[编辑]:不是这样的。我刚试了一下,一个简单的TForm与一个菜单项显示了加速器,但只要我添加一个TImageList并设置单个菜单项的ImageIndex,或者只是将OwnerDraw设置为true,那么加速器下划线就消失了。我想这确实是VCL中的一个bug。
顺便说一下,这是在Windows XP上。
解决方法:
我已经在Windows XP 64上使用Delphi 2009进行了调试,缺少加速器的根本原因似乎是Windows发送带有ODS_NOACCEL标志的WM_DRAWITEM消息,如果系统设置为始终显示加速器,则不应该这样。因此,您可以说这不是VCL的错误,而是Windows的问题,VCL无法解决。
但是,在您自己的代码中可以解决它,您只需要在将消息传递给VCL之前重置该标志即可。覆盖窗口过程。
protected
procedure WndProc(var Message: TMessage)
像这样:
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
消息时再调用。
WndProc
中我总是调用pDIS^.itemState := pDIS^.itemState and not ODS_NOACCEL;
确保ODS_NOACCEL
标志被排除,但不幸的是它没有生效。有什么提示吗?谢谢。 - Edwin Yip