TLabel отображает клавиши ускорения, даже когда состояние пользовательского интерфейса говорит не

При настройках Windows по умолчанию клавиши ускорения не должны отображаться в диалоговых окнах, пока пользователь не нажмет клавишу ALT.

Делфи TLabel контроль не подчиняется этому соглашению, как показано ниже:

Хотя для ярлыка и флажка указана клавиша ускорения, флажок правильно скрывает ее, а для ярлыка - нет. Конечно, когда нажата ALT, акселератор показывает для флажка, но это поведение до того, что является неправильным.

Я понимаю, почему это происходит, потому что код VCL, который реализует это поведение, содержится в TWinControl например UpdateUIState метод и полагается на отправку базового оконного элемента управления WM_CHANGEUISTATE сообщение. поскольку TLabel не оконный, он пропускает эту обработку.

Кто-нибудь может предложить способ достижения желаемого поведения для неоконных элементов управления?

Обновление 1

Я только что обнаружил, что групповые блоки и радиогруппы также не реагируют на состояние пользовательского интерфейса.

Обновление 2

КК № 97044.

3 ответа

Решение

Я думаю, что я разработал способ справиться с этим.

function HideAccelFlag(Control: TControl): Integer;
begin
  //ask the top level window about its UI state
  while Assigned(Control.Parent) do begin
    Control := Control.Parent;
  end;
  if (Control.Perform(WM_QUERYUISTATE, 0, 0) and UISF_HIDEACCEL)=UISF_HIDEACCEL then begin
    Result := DT_HIDEPREFIX;
  end else begin
    Result := 0;
  end;
end;

type
  TUIStateAwareLabel = class(TLabel)
  protected
    procedure DoDrawText(var Rect: TRect; Flags: Longint); override;
  end;

procedure TUIStateAwareLabel.DoDrawText(var Rect: TRect; Flags: Integer);
begin
  if ShowAccelChar then begin
    Flags := Flags or HideAccelFlag(Self);
  end;
  inherited;
end;

Я уверен, что я всегда создаю TUIStateAwareLabel скорее, чем TLabel подключив механизм потоковой передачи формы с TReader.OnFindComponentClass,

Имея дело с TCustomGroupBox потомки более грязные. Для них я прибег к копированию исходного кода TCustomGroupBox.Paint в мой потомок и используя HideAccelFlag снова.

Следующая задача - записать его в виде отчета о контроле качества.

Вы могли бы использовать TStaticText вместо TLabel,

Со страницы документа:

Используйте TStaticText вместо TLabel, когда клавиша ускорения компонента должна принадлежать оконному элементу управления.

Извините, нет кода, но, возможно, направление решения.

Я вижу TWinControl используя NotifyControls для широковещательной рассылки сообщения всем содержащимся элементам управления. Он используется для уведомления органов управления об изменениях в Parent* свойства, например

procedure TWinControl.CMShowHintChanged(var Message: TMessage);
begin
  inherited;
  NotifyControls(CM_PARENTSHOWHINTCHANGED);
end;

Я думаю, что вы могли бы сделать, это кодировать обработчик сообщений в вашей форме, чтобы получить WM_CHANGEUITSTATE и передать его всем элементам управления, связанным с формой, используя либо NotifyControls, либо что-то подобное, что только передает его в контейнеры и TLabels.

Тогда вам все еще нужен способ, чтобы ваша TLabel реагировала на это сообщение. Я предполагаю (не рассматривал это), что вы можете либо переопределить (потомок или перехватчик) метод WndProc и / или сделать что-то с FDefWndProc (защищенное свойство).

И вам придется обслуживать кадры в формах в...

Другие вопросы по тегам