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 does not obey this convention, as shown below:
Although both label and check box have an accelerator key specified, the check box correctly hides it, but the label does not. Of course, when ALT is pressed, the accelerator shows for the check box, but it's the behaviour prior to that which is incorrect.
My understanding of why this happens is that the VCL code that implements this behaviour is contained in TWinControl
, for example the UpdateUIState
method, and relies on sending the underlying windowed control a WM_CHANGEUISTATE
message. Since TLabel
is not windowed, it misses out on this handling.
Can anybody suggest a way to achieve the desired behaviour for non-windowed controls?
Update 1
I've just discovered that group boxes and radio groups don't respond to UI state either.
Update 2
QC#97044.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With