With default Windows settings, accelerator keys are not meant to be shown on dialogs until the user presses the ALT key.
Delphi\'s TLabel
control
You could use TStaticText instead of TLabel
.
From the doc page:
Use TStaticText instead of TLabel when the component's accelerator key must belong to a windowed control.
I think I've worked out a way of handling it.
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;
I make sure that I always create TUIStateAwareLabel
rather than TLabel
by hooking the form streaming mechanism with TReader.OnFindComponentClass
.
Dealing with TCustomGroupBox
descendents is more messy. For them I resorted to copying the source code of TCustomGroupBox.Paint
into my descendent and making use of HideAccelFlag
again.
Next task is to write it up as a QC report.
Sorry no code, but maybe a solution direction.
I see TWinControl using NotifyControls
to BroadCast a message to all contained controls. It is used to notify controls of changes in the Parent
* properties, for example
procedure TWinControl.CMShowHintChanged(var Message: TMessage);
begin
inherited;
NotifyControls(CM_PARENTSHOWHINTCHANGED);
end;
I guess what you could do is code a message handler on your form to get the WM_CHANGEUITSTATE and pass it on to all controls parented by the form, using either NotifyControls, or something similar that only passes it to containers and TLabels.
You then still need a way to have your TLabel's' react to that message. I guess (haven't looked into it) that you could either override (descendant or interceptor) the WndProc method and/or do something with FDefWndProc (protected property).
And you will have to cater for frames in forms in ...