【问题标题】:How can I show a tooltip on a disabled button?如何在禁用按钮上显示工具提示?
【发布时间】:2009-01-29 11:26:13
【问题描述】:

如果您在 winform 上有一个禁用按钮,如何在鼠标悬停时显示工具提示以告知用户该按钮为何被禁用?

【问题讨论】:

  • 如果功能被更改,这样工具提示在禁用时仍然显示,那就太好了。有什么更好的时间来帮助用户!我决定让按钮保持启用状态,只显示一个 msgbox 来解释为什么不会采取该操作。哎呀。

标签: c# .net winforms


【解决方案1】:

将按钮(或任何适合此场景的控件)放置在容器(面板、tableLayoutPanel)中,并将工具提示与相应的底层面板单元格相关联。在多种情况下都可以很好地工作,灵活。提示:使单元格足够大以容纳 bttn,因此鼠标悬停响应(工具提示显示)不会出现在 bttn 边界之外“流血”。

【讨论】:

  • 好主意,但意味着你的控制数加倍,
  • 嘿@SamMackrill(对不起,延迟响应,但为了后代),真正的数据,但应该只适用于需要它的 ctrls(通常只是几个)避免了很多不必要的代码/复杂性,使实现可视化,以便非开发人员(例如设计师)可以实现/维护。以 pkg 的方式创建已经以这种方式配置的自定义 crtls 可能会很方便。
  • 这是迄今为止最优雅的答案。如果您需要 TableLayoutPanel 单元格上的工具提示,则必须在单元格中放置一个面板,然后在面板中放置您的控件,因为无法引用 TableLayoutPanel 单元格 - 只能引用它们包含的控件。
  • 我将工具提示添加到包含禁用按钮的 GroupBox 中。这意味着每当用户将鼠标悬停在禁用按钮附近的任何位置时都会弹出工具提示,但我认为这不是问题。
  • 听起来你可能在我的回答中遇到了提示“出血”的问题;确保包含面板不大于禁用的 bttn。
【解决方案2】:

此后我将 BobbyShaftoe 的答案改编得更笼统

注意事项:

  • 必须在父控件上设置 MouseMove 事件(在我的例子中是一个面板)

    private void TimeWorks_MouseMove(object sender, MouseEventArgs e)
    {
        var parent = sender as Control;
        if (parent==null)
        {
            return;
        }
        var ctrl = parent.GetChildAtPoint(e.Location);
        if (ctrl != null && !ctrl.Enabled)
        {
            if (ctrl.Visible && toolTip1.Tag==null)
            {
                var tipstring = toolTip1.GetToolTip(ctrl);
                toolTip1.Show(tipstring, ctrl, ctrl.Width / 2, ctrl.Height / 2);
                toolTip1.Tag = ctrl;
            }
        }
        else
        {
            ctrl = toolTip1.Tag as Control;
            if (ctrl != null)
            {
                toolTip1.Hide(ctrl);
                toolTip1.Tag = null;
            }
        }
    
    }
    

【讨论】:

  • 小修饰:在第二个 if 中,您可能需要添加条件 && !ctrl.Enabled,以便在快速切换到另一个实际处于活动状态的子控件时正确消失(需要特殊我认为布局是可重现的)。
【解决方案3】:

Sam Mackrill,感谢您的回答,使用标签了解您要离开的控件是个好主意。但是,根据 BobbyShaftoe 的回答,您仍然需要 IsShown 标志。如果你把鼠标放在了错误的位置,如果工具提示出现在它下面,它可以触发另一个 MouseMove 事件(即使你没有物理移动鼠标)。这可能会导致一些不需要的动画,因为工具提示会不断消失并重新出现。

这是我的代码:

    private bool toolTipShown = false;
    private void TimeWorks_MouseMove(object sender, MouseEventArgs e)
    {
        var parent = sender as Control;
        if (parent == null)
        {
            return;
        }
        var ctrl = parent.GetChildAtPoint(e.Location);
        if (ctrl != null)
        {
            if (ctrl.Visible && toolTip1.Tag == null)
            {
                if (!toolTipShown)
                {
                    var tipstring = toolTip1.GetToolTip(ctrl);
                    toolTip1.Show(tipstring.Trim(), ctrl, ctrl.Width / 2, ctrl.Height / 2);
                    toolTip1.Tag = ctrl;
                    toolTipShown = true;
                }
            }
        }
        else
        {
            ctrl = toolTip1.Tag as Control;
            if (ctrl != null)
            {
                toolTip1.Hide(ctrl);
                toolTip1.Tag = null;
                toolTipShown = false;
            }
        }
    }

【讨论】:

  • 每次鼠标移动都会触发这个是否存在资源问题?
  • 当控件在 TabControl 中时不起作用。 GetChildAtPoint() 返回 TabControl 而不是子控件。
  • @PeterSmartt:当parent 控件本身具有工具提示时,您描述的情况仅发生在我身上,否则@SamMackrill 的代码对我来说很好用。 @flixfe:如果您使用 TabControl,则可以执行 if (ctrl.GetType().IsInstanceOfType(typeof(TabControl))) ctrl = ((TabControl)ctrl).SelectedTab; 之类的操作以获取当前选定的选项卡。
  • 在尝试了几个小时后,我找不到令人满意的解决方案。我终于用MessageBox 解决了我的问题。但是,我认为在某些情况下,所提议的 ToolTip 是一个优雅的解决方案。
【解决方案4】:

因此,假设您的控件名为 button1,您可以执行以下操作。
您必须通过处理表单的 MouseMove 事件来做到这一点,因为这些事件不会从您的控件中触发。

bool IsShown = false;      

void Form1_MouseMove(object sender, MouseEventArgs e)
{
   Control ctrl = this.GetChildAtPoint(e.Location);

   if (ctrl != null)
   {
       if (ctrl == this.button1 && !IsShown)
       {
           string tipstring = this.toolTip1.GetToolTip(this.button1);                 
           this.toolTip1.Show(tipstring, this.button1, this.button1.Width /2, 
                                                       this.button1.Height / 2);
           IsShown = true;
       }
   }
   else
   {
       this.toolTip1.Hide(this.button1);
       IsShown = false;
   }

}

【讨论】:

    猜你喜欢
    • 2016-06-15
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 2020-12-03
    • 2021-02-27
    相关资源
    最近更新 更多