Menu Accelerator Keys Not Showing Up (Delphi 2009)

回眸只為那壹抹淺笑 提交于 2019-11-28 09:22:46

There is a standard Windows setting (under display properties) to normally hide those accelerators unless the Alt key is held down. That would explain why opening the menu with Alt+F10 shows them for you. Maybe that's the cause?

[EDIT]: No, it's not. I just tried, and a simple TForm with a menu item shows the accelerator, but as soon as I add a TImageList and set the ImageIndex of the single menu item, or simply set OwnerDraw to true, then the accelerator underline disappears. I guess that really is a bug in the VCL.

BTW, this is on Windows XP.

Workaround:

I have debugged this using Delphi 2009 on Windows XP 64, and the root cause for the missing accelerators seems to be that Windows sends WM_DRAWITEM messages with the ODS_NOACCEL flag set, which it shouldn't if the system is set to show accelerators at all times. So you could say that it is not a VCL bug, but a Windows problem which the VCL does not work around.

However, you can work around it in your own code, you just need to reset the flag before passing the message to the VCL. Override the window proc

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

like so:

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;

This is demonstration code only, you should not call SystemParametersInfo() every time a WM_DRAWITEM message is received, but once at program start, and then every time your program receives a WM_SETTINGCHANGE message.

It is a "feature" introduced with Windows 2000:

The Old New Thing: Why does Windows hide keyboard accelerators and focus rectangles by default?

It would appear that Delphi 4 didn't support this Windows feature.

To have 2000 and XP menus show accelerator keys, right-click an empty spot on the desktop, choose Properties, click the Appearance tab, and under Effects, uncheck Hide Underlined Letters for Keyboard Navigation until I Press the Alt Key. Click OK twice.

Not sure how to do it in Vista.

I don't think it is a Delphi generated bug as you have the same behavior with Notepad on Vista. Also in Delphi itself BTW...
I must confess that I did not pay attention before your question. Thanks for pointing it out.

As Jim McKeeth noted above (correctly), this is "by design" behavior. If the menus are triggered through keyboard action the accelerators should be shown, but if triggered by the mouse the accelerators are intentionally not shown.

I have my XP configured to show accelerators at all times, but a quick test with that option changed confirms that the menus should not show underlines either (Visual Studio responded as I expected, no underlines when using the mouse). However, Microsoft Office ignores this setting and always shows the underlines. So it looks like a bug in how the menus are drawn in Delphi (I don't have any experience with Delphi myself).

I found the option for Vista as well: http://www.vistax64.com/vista-general/42125-always-show-menu-underline-keyboard-accelerators.html

You can turn this on in the new Ease of Access Center (go to Control Panel, click Ease of Access and then click Ease of Access Center). In the Ease of Access Center, click Make the keyboard easier to use, and at the very bottom select the Underline keyboard shortcuts and access keys check box.

While doing further research I found this related bug on Delphi forums: http://qc.codegear.com/wc/qcmain.aspx?d=37403

It looks like in your case the child windows (the drawn menus) aren't getting or aren't handling WM_UIUPDATESTATE message from their parent window, which is what causes the redraw with accelerators.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!