Существует стандартная настройка Windows (в свойствах дисплея), чтобы обычно скрывать эти ускорители, если не удерживать клавишу Alt. Это объясняет, почему открытие меню с помощью Alt + F10 показывает их для вас. Может в этом причина?
[РЕДАКТИРОВАТЬ]: Нет, это не так. Я только что попробовал, и простая TForm с элементом меню показывает ускоритель, но как только я добавляю TImageList и устанавливаю ImageIndex одного элемента меню, или просто устанавливаю OwnerDraw в true, подчеркивание ускорителя исчезает. Я думаю, что это действительно ошибка в VCL.
Кстати, это на Windows XP.
Обход:
Я отладил это с помощью Delphi 2009 в Windows XP 64, и основной причиной отсутствия ускорителей, по-видимому, является то, что Windows отправляет WM_DRAWITEM
сообщения с установленным флагом ODS_NOACCEL
, чего не следует делать, если система установить показывать ускорители все время. Таким образом, вы можете сказать, что это не ошибка VCL, а проблема Windows, которая не работает в VCL.
Однако вы можете обойти это в своем собственном коде, вам просто нужно сбросить флаг перед передачей сообщения в VCL. Переопределить окно proc
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;
Это только демонстрационный код, вы не должны вызывать SystemParametersInfo()
каждый раз, когда принимается сообщение WM_DRAWITEM
, но один раз при запуске программы, а затем каждый раз, когда ваша программа получает сообщение WM_SETTINGCHANGE
.