即使UI状态说不,TLabel也会显示加速键

时间:2011-08-02 12:56:17

标签: delphi

使用默认的Windows设置,在用户按下 ALT 键之前,加速键不会显示在对话框上。

Delphi的TLabel控件不符合此约定,如下所示:

虽然标签和复选框都指定了加速键,但复选框会正确隐藏它,但标签不会。当然,当按下 ALT 时,加速器显示复选框,但它是之前的行为是不正确的。

我理解这种情况的原因是实现此行为的VCL代码包含在TWinControl中,例如UpdateUIState方法,并依赖于发送基础窗口控件{{1} } 信息。由于WM_CHANGEUISTATE没有窗口化,因此在此处理中错失了。

有人能建议一种方法来实现非窗口控件的预期行为吗?

更新1

我刚刚发现组框和广播组也没有响应UI状态。

更新2

QC#97044

3 个答案:

答案 0 :(得分:7)

我想我已经找到了处理它的方法。

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

接下来的任务是将其写成QC报告。

答案 1 :(得分:2)

您可以使用TStaticText代替TLabel

从文档页面:

  

当组件的加速键必须属于窗口控件时,请使用TStaticText而不是TLabel。

答案 2 :(得分:0)

抱歉没有代码,但可能是解决方案。

我看到TWinControl使用NotifyControls向BroadCast发送包含所有控件的消息。它用于通知控件Parent *属性的变化,例如

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

我猜你可以做的是在你的表单上编写一个消息处理程序来获取WM_CHANGEUITSTATE并将其传递给表单的所有控件,使用NotifyControls,或类似的只传递给容器和TLabels的东西。 / p>

然后你仍然需要一种方法让你的TLabel'对这条消息作出反应。我想(没有调查过)你可以覆盖(后代或拦截器)WndProc方法和/或用FDefWndProc(受保护属性)做一些事情。

你必须在......中的表格中提供框架。