使用默认的Windows设置,在用户按下 ALT 键之前,加速键不会显示在对话框上。
Delphi的TLabel
控件不符合此约定,如下所示:
虽然标签和复选框都指定了加速键,但复选框会正确隐藏它,但标签不会。当然,当按下 ALT 时,加速器显示复选框,但它是之前的行为是不正确的。
我理解这种情况的原因是实现此行为的VCL代码包含在TWinControl
中,例如UpdateUIState
方法,并依赖于发送基础窗口控件{{1} } 信息。由于WM_CHANGEUISTATE
没有窗口化,因此在此处理中错失了。
有人能建议一种方法来实现非窗口控件的预期行为吗?
更新1
我刚刚发现组框和广播组也没有响应UI状态。
更新2
答案 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)
答案 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(受保护属性)做一些事情。
你必须在......中的表格中提供框架。