【问题标题】:How to send an hint message by code?如何通过代码发送提示消息?
【发布时间】:2017-02-09 04:37:02
【问题描述】:

如何向应用程序发送提示消息? 我尝试了一个小测试:

  TForm1 = class(TForm)
    ApplicationEvents1: TApplicationEvents;
    Memo1: TMemo;
    procedure ApplicationEvents1Hint(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure TForm1.ApplicationEvents1Hint(Sender: TObject);
begin
  Memo1.Lines.Add(Application.Hint);
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  Application.Hint := 'Hello';
end;

观察 Memo1 的台词,似乎每次我设置 'Hello' 时都会发送一条空提示消息。

在实际场景中,空提示消息会隐藏我的提示消息,我不明白我在做什么错,这是错误的做法吗?

【问题讨论】:

    标签: delphi hint


    【解决方案1】:

    我怀疑您真正想做的是在鼠标移到控件上时调整当前显示的提示。为此,您可以使用TApplication.OnShowHintTApplicationEvents.OnShowHint 事件,或子类化目标控件来处理CM_HINTSHOW 消息。其中任何一个都将提供对您可以自定义的THintInfo 记录的访问,例如:

    procedure TForm1.ApplicationEvents1ShowHint(var HintStr: string;
      var CanShow: Boolean; var HintInfo: THintInfo)
    begin
      // HintInfo.HintControl is the control that is about to display a hint
      if HintInfo.HintControl = Memo1 then
      begin
        // HintInfo.CursorPos is the current mouse position within the HintControl
        HintStr := Format('Hello, cursor = %d,%d', [HintInfo.CursorPos.X, HintInfo.CursorPos.Y]);
    
        // the hint will remain active until it times out (see
        // TApplication.HintHidePause and THintInfo.HideTimeout) or
        // the mouse moves outside of the HintInfo.CursorRect.  In
        // the latter case, a new hint will be displayed. This allows
        // you to change the hint for different sections of the
        // HintControl. The CursorRect is set to the HintControl's
        // whole client area by default.
    
        // In this example, setting the new CursorRect to a 1x1 square
        // around the current CursorPos will display a new hint string
        // on each mouse movement...
        HintInfo.CursorRect := Rect(HintInfo.CursorPos.X, HintInfo.CursorPos.Y, HintInfo.CursorPos.X, HintInfo.CursorPos.Y);
      end;
    end;
    

    请注意,以这种方式自定义显示的提示不会在每次提示更改时触发TApplication.OnHint/TApplicationEvents.OnHint 事件,只有在显示新的提示弹出时才会触发。 OnShowHint/CM_HINTSHOW 允许您对现有提示弹出窗口执行实时更新。

    【讨论】:

      【解决方案2】:

      您不应该直接设置Application.Hint。该框架从TApplication.Idle 开始执行此操作。这样做是这样的:

      Control := DoMouseIdle;
      if FShowHint and (FMouseControl = nil) then
        CancelHint;
      Application.Hint := GetLongHint(GetHint(Control));
      

      这里Control 是鼠标下的任何控件。由于您没有为程序中的任何控件指定Hint 属性,因此每当执行此代码时,它会将Application.Hint 设置为''

      所以,这就是发生的事情:

      • 您移动鼠标:
      • 您的鼠标移动处理程序通过设置Application.Hint 对此作出响应。
      • 消息队列被清空,TApplication.OnIdle 执行。
      • 这会将Application.Hint 更新回''

      然后你回到起点,来回重复。

      所以,是的,这确实是错误的方法。究竟什么是正确的方法,我无法真正说出,因为我不知道你真正的问题。通常,您为操作、菜单项、按钮、工具按钮等组件设置Hint 属性。但也许您的需求更加动态。我无法与他们交谈,但我相信我已经解释了为什么你会观察到这种行为。

      我觉得值得一提的另一点是提示是非常有趣的野兽。您永远不会以同步方式显示提示。您等到系统决定要显示提示,然后以一种或另一种方式向其提供提示的内容。当应用程序空闲时,通常会在鼠标停止移动时显示提示。您的代码试图强制在OnMouseMove 事件中显示提示,最好将其描述为跨框架工作的代码。

      【讨论】:

      • 感谢您的明确解释。我会记住这一点的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-27
      相关资源
      最近更新 更多