TLabel отображает клавиши ускорения, даже когда состояние пользовательского интерфейса говорит не
При настройках Windows по умолчанию клавиши ускорения не должны отображаться в диалоговых окнах, пока пользователь не нажмет клавишу ALT.
Делфи TLabel
контроль не подчиняется этому соглашению, как показано ниже:
Хотя для ярлыка и флажка указана клавиша ускорения, флажок правильно скрывает ее, а для ярлыка - нет. Конечно, когда нажата ALT, акселератор показывает для флажка, но это поведение до того, что является неправильным.
Я понимаю, почему это происходит, потому что код VCL, который реализует это поведение, содержится в TWinControl
например UpdateUIState
метод и полагается на отправку базового оконного элемента управления WM_CHANGEUISTATE
сообщение. поскольку TLabel
не оконный, он пропускает эту обработку.
Кто-нибудь может предложить способ достижения желаемого поведения для неоконных элементов управления?
Обновление 1
Я только что обнаружил, что групповые блоки и радиогруппы также не реагируют на состояние пользовательского интерфейса.
Обновление 2
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 (защищенное свойство).
И вам придется обслуживать кадры в формах в...