TLabel displays accelerator keys even when the UI state says not to

后端 未结 3 619
故里飘歌
故里飘歌 2021-02-09 09:35

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

相关标签:
3条回答
  • 2021-02-09 10:09

    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.

    0 讨论(0)
  • 2021-02-09 10:12

    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.

    0 讨论(0)
  • 2021-02-09 10:21

    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 ...

    0 讨论(0)
提交回复
热议问题