【问题标题】:Delphi XE2: OnHideHint event to automatically restore the previous text in the StatusBar?Delphi XE2:OnHideHint事件自动恢复StatusBar之前的文字?
【发布时间】:2013-06-06 15:32:18
【问题描述】:

TAction 有一个 OnHint 事件,但不幸的是没有一个 OnHideHint 事件。这有以下缺点: 我有 ToolButtons 和其他与操作相关的控件。每当鼠标悬停在这样的控件上时,Action 的提示就会显示在 StatusBar 中; (我已将 StatusBar 的 AutoHint 属性设置为 True)。但是当鼠标离开 ToolButton 时,StatusBar 中先前的自定义文本(不是来自提示)不会自动恢复! 现在我可以为表单上的每个控件编写一个 OnMouseLeave 事件处理程序来恢复我在状态栏中的自定义文本,但这会很麻烦! 不是有什么东西可以自动恢复状态栏中的先前文本吗? TAction 中的 OnHideHint 事件非常理想!

【问题讨论】:

    标签: delphi delphi-xe2 statusbar hint hints


    【解决方案1】:

    这是默认行为,当 AutoHint 为 True 时,状态栏会通过在第一个面板中显示提示文本的长版本来自动响应提示操作。

    您遇到的问题是,当您用鼠标离开控件时,您基本上进入了另一个窗口,它是父控件。并且因为该父级没有分配给它的提示字符串值,所以提示动作被更新为一个空字符串。

    如果您想在没有提示显示时返回默认值,则在表单上放置一个TApplicationEvents 组件并使用 TApplication.OnHint 事件,如下所示:

    var
      OriginalPanelText : String = 'BLA';
    
    procedure TForm1.ApplicationEvents1Hint(Sender: TObject);
    begin
    
       if StatusBar1.SimplePanel or (StatusBar1.Panels.Count = 0)
      then
        if Application.Hint <> ''
        then
           StatusBar1.SimpleText := Application.Hint
        else
           StatusBar1.SimpleText := OriginalPanelText
      else
        if Application.Hint <> ''
        then
          StatusBar1.Panels[0].Text := Application.Hint
        else
          StatusBar1.Panels[0].Text := OriginalPanelText;
    
    end;
    

    【讨论】:

      【解决方案2】:

      AutoHint 的魔法全部发生在TStatusBar.ExecuteAction。当提示停止显示该代码时,会将状态栏文本设置为空。您可以像这样修改行为:

      type
        TStatusBar = class(ComCtrls.TStatusBar)
        private
          FRestoreTextAfterHintAction: string;
        public
          function ExecuteAction(Action: TBasicAction): Boolean; override;
        end;
      
      function TStatusBar.ExecuteAction(Action: TBasicAction): Boolean;
      var
        HintText: string;
      begin
        if AutoHint and not (csDesigning in ComponentState) and
           (Action is THintAction) and not DoHint then begin
          HintText := THintAction(Action).Hint;
          if SimplePanel or (Panels.Count=0) then begin
            if HintText='' then begin
              SimpleText := FRestoreTextAfterHintAction;
            end else begin
              FRestoreTextAfterHintAction := SimpleText;
              SimpleText := HintText;
            end;
          end else begin
            if HintText='' then begin
              Panels[0].Text := FRestoreTextAfterHintAction;
            end else begin
              FRestoreTextAfterHintAction := Panels[0].Text;
              Panels[0].Text := HintText;
            end;
          end;
          Result := True;
        end else begin
          Result := inherited ExecuteAction(Action);
        end;
      end;
      

      我使用了一个相当粗糙的插入器类和一个脆弱的实例变量来存储要恢复的文本。如果你愿意,你可以把它弄得更健壮一些。上面的代码至少显示了你需要添加钩子的地方。

      【讨论】:

      • 正要解释,但在我发表评论之前你删除了它。这是我第一次对你的一个答案投了反对票,并且有充分的理由,我不认为有必要通过使用插入器类和修改函数来解决问题,因为你可以用更简单的方式做到这一点,为什么当显然已经实施了解决方法时,开始破解它吗?而且我不知道你为什么会在我之后 12 小时发帖,显然我已经解释了为什么会发生这种情况并提供了一个很好的解决方案,然后再搞砸我 idk。
      • @Peter 这只是一种不同的方式。将行为封装在控件中可以避免必须添加Application.OnHint 处理程序。 12 小时前的答案的存在与这些有什么关系?我想你需要在这里放松一下。没有人愿意“跟你开玩笑”。看在上帝的份上,这只是一个 SO 答案!
      • @PeterVonča 我不介意投反对票。无论如何,它需要你的代表! ;-)
      • 感谢两位的好主意!我喜欢 Peter Vonča 解决方案的简单性和 David Heffernan 解决方案的 OOP 方法。因为我的代码中的情况相当复杂,所以我实际上在两种解决方案中都使用了混合思想的修改。谢谢 - 所以规则!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-15
      • 1970-01-01
      • 2012-08-08
      • 2013-06-12
      • 1970-01-01
      • 2016-04-06
      • 1970-01-01
      相关资源
      最近更新 更多