I've tried my best and cannot figure out what happened here. It worked fine in Delphi 4. After upgrading to Delphi 2009, I don't know if this is the way it is supposed to work, or if it's a problem:
This is what my program's menu looks like in Design Mode under Delphi 2009:
Notice that every word in the Main Menu and the File submenu have one letter underlined. It is supposed to be like this. This underlined letter is called the Accelerator Key and is standard in Windows applications so that you can use the Alt-key and that letter to quickly select the menu item and then submenu item with the keyboard rather than with your mouse.
You get them this way by using the "&" character as part of the caption of the item, for example: Save &As...
When I run my application, and use the mouse to open the File menu, it looks like this:
The characters are underlined in the main menu, but are not underlined in the File menu.
If instead, I use the Alt-F key to open up the File submenu, then it looks correct like this:
and all the Accelerator Key letters are properly underlined.
I've played with the AutoHotKeys option but that's not the problem.
Has someone encountered this problem before? Is the example in the 2nd image correct behavior that I don't know of? Or is there some option or coding mistake that I might have missed?
Nov 2009 (one year later): mghie seems to have got to the root of this and figured out the problem. See his accepted answer below.
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.