TLabel displays accelerator keys even when the state of the user interface says no

With standard Windows settings, accelerator keys are not displayed in the dialog box until the user presses the ALT key.

The Delphi TLabel does not obey this convention, as shown below:

Although the accelerator key is indicated on the label and flag, the flag hides it correctly, but not on the label. Of course, when the ALT key is pressed, this checkbox is displayed, but this behavior is so wrong.

My understanding of why this happens is that the VCL code that implements this behavior is contained in TWinControl , for example, the UpdateUIState method, and relies on sending a basic windowed control. Since TLabel not finished, it skips this processing.

Can anyone suggest a way to achieve the desired behavior for non-window controls?

Update 1

I just found that group fields and radio groups do not respond to the state of the user interface.

Update 2

QC # 97044 .

+6
source share
3 answers

I think I developed a processing method.

 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 am sure that I always create TUIStateAwareLabel , not TLabel , by connecting the form streaming mechanism using TReader.OnFindComponentClass .

Working with descendants of TCustomGroupBox more dirty. For them, I resorted to copying the source code of TCustomGroupBox.Paint to my descendant and again using HideAccelFlag .

The next task is to write it in the form of a quality control report.

+6
source

You can use TStaticText instead of TLabel .

On the document page:

Use TStaticText instead of TLabel when the component accelerator key must belong to a window control.

+2
source

Sorry code, but maybe the direction of the solution.

I see TWinControl using NotifyControls for BroadCast for all contained controls. It is used to notify Parent * property change controls, for example

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

I assume that you could make the message handler code in your form to get WM_CHANGEUITSTATE and pass it to all controls native to the form using either NotifyControls or something similar that only passes it to containers and TLabels.

Then you still need your TLabel to "respond to this message." I assume (did not look at it) that you can either override (the child or interceptor) the WndProc method and / or do something using FDefWndProc (protected property).

And you have to serve frames in forms in ...

0
source

Source: https://habr.com/ru/post/894104/


All Articles