在Delphi中拦截提示事件

4

我正在尝试在组件内部临时更改提示文本,而不更改Hint属性本身。

我尝试捕获CM_SHOWHINT事件,但是这个事件似乎只会到达窗体,而不是组件本身。

插入CustomHint也不起作用,因为它使用Hint属性中的文本。

我的组件继承自TCustomPanel

以下是我的尝试:

procedure TImageBtn.WndProc(var Message: TMessage);
begin
  if (Message.Msg = CM_HINTSHOW) then
    PHintInfo(Message.LParam)^.HintStr := 'CustomHint';
end;

我在互联网上找到了这段代码,但是很遗憾它并不能正常工作。

2个回答

11

CM_HINTSHOW 确实就是你需要的。以下是一个简单的示例:

type
  TButton = class(Vcl.StdCtrls.TButton)
  protected
    procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
  end;

  TMyForm = class(TForm)
    Button1: TButton;
  end;

....

procedure TButton.CMHintShow(var Message: TCMHintShow);
begin
  inherited;
  if Message.HintInfo.HintControl=Self then
    Message.HintInfo.HintStr := 'my custom hint';
end;
问题中的代码没有调用 inherited,这可能是导致失败的原因。或者可能是类声明中省略了 WndProcoverride 指令。不管怎样,按照我在这个答案中的方式更加清晰。

您也可以使用TApplication.OnShowHint事件来完成相同的事情。 - Remy Lebeau
1
@Remy 两种方法都有优缺点。如果你正在编写一个组件,那么使用消息是最好的选择。如果你想应用于整个应用程序的策略,那么OnShowHint则更胜一筹。 - David Heffernan

6

您可以使用OnShowHint事件

这个参数有HintInfo参数:http://docwiki.embarcadero.com/Libraries/XE3/en/Vcl.Forms.THintInfo

该参数允许您查询提示控件、提示文本以及所有上下文,并在必要时覆盖它们。

如果您想过滤要更改提示的组件,可以声明一些ITemporaryHint接口之类的内容。

type 
  ITemporaryHint = interface 
  ['{1234xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}']
    function NeedCustomHint: Boolean;
    function HintText: string;
  end;

然后您可以通用地检查任何组件是否实现了该接口

procedure TForm1.DoShowHint(var HintStr: string; var CanShow: Boolean;
  var HintInfo: THintInfo);
var
  ih: ITemporaryHint;
begin
  if Supports(HintInfo.HintControl, {GUID for ITemporaryHint}, ih) then
    if ih.NeedCustomHint then
      HintInfo.HintStr := ih.HintText;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.ShowHint := True;
  Application.OnShowHint := DoShowHint;
end;  

1
哦,@TLama,同时进行这些替换似乎是不一致的:boolean -> Boolean 和 String - string。然而,DoShowHint声明直接来自Delphi DocWiki示例。我会相信他们选择String的理由。 - Arioch 'The

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接