在一个控件上多次显示WinForms Tooltip?

时间:2013-10-06 03:44:07

标签: c# .net winforms tooltip

我正在尝试在自定义绘制的(WinForms)UserControl上使用WinForms Tooltip类(使用GDI +)。它是遗留代码,但我需要再保持几年。我希望在光标在不同的地方暂停时显示工具提示。在光标暂停之前,我不想进行计算以了解是否应该显示工具提示,这有助于确定Popup事件中的信息。在下面的非工作示例代码中,我希望我可以将光标移动到窗体上的任何角落并查看工具提示。似乎如果我点击删除工具提示,我从未见过。第一个展示的工具提示并不像我预期的那样直接。我如何使这项工作?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestToolTip
{
    public partial class Form1 : Form
    {
        private readonly ToolTip _tooltip = new ToolTip();
        public Form1()
        {
            InitializeComponent();

            _tooltip.AutoPopDelay = 10000;
            _tooltip.InitialDelay = 1000;
            _tooltip.ReshowDelay = 200;

            _tooltip.Popup += OnTooltipPopup;
            _tooltip.SetToolTip(this, "you should never see this"); // we need something or it won't ever trigger Popup
        }

        private Point _lp;
        protected override void OnMouseMove(MouseEventArgs e)
        {
            _lp = e.Location;
            base.OnMouseMove(e);
        }

        void OnTooltipPopup(object sender, PopupEventArgs e)
        {
            string text = null;
            if (_lp.X < 100 && _lp.Y < 100)
                text = "Top Left";
            else if (_lp.X < 100 && _lp.Y > Height - 100)
                text = "Bottom Left";
            else if (_lp.X > Width - 100 && _lp.Y < 100)
                text = "Top Right";
            else if (_lp.X > Width - 100 && _lp.Y > Height - 100)
                text = "Bottom Right";

            var existing = _tooltip.GetToolTip(this);
            if (existing == text) 
                return;

            if (text != null)
                _tooltip.SetToolTip(this, text); // calls into this method

            e.Cancel = true;
        }
    }
}

3 个答案:

答案 0 :(得分:1)

不是很优雅,但您可以使用Timer跟踪鼠标在您的控件中何时处于空闲状态,并更新Elapsed事件中的工具提示。

示例:

public partial class Form1 : Form
{
    private readonly ToolTip _tooltip = new ToolTip();
    private readonly System.Timers.Timer _mouseIdleTimer = new System.Timers.Timer();

    public Form1()
    {
        InitializeComponent();

        MouseLeave += Form1_MouseLeave;
        MouseMove += Form1_MouseMove;

        _mouseIdleTimer.AutoReset = false;
        _mouseIdleTimer.Interval = 900;
        _mouseIdleTimer.Elapsed += _mouseIdleTimer_Elapsed;

        _tooltip.AutoPopDelay = 10000;
        _tooltip.InitialDelay = 1000;
        _tooltip.ReshowDelay = 200;
    }

    void Form1_MouseLeave(object sender, EventArgs e)
    {
        _mouseIdleTimer.Stop();
    }

    private Point _lp;
    void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        _lp = e.Location;

        // Mouse still moving, restart the countdown
        _mouseIdleTimer.Stop();
        _mouseIdleTimer.Start();
    }

    void _mouseIdleTimer_Elapsed(object sender, EventArgs e)
    {
        string text = null;
        if (_lp.X < 100 && _lp.Y < 100)
            text = "Top Left";
        else if (_lp.X < 100 && _lp.Y > Height - 100)
            text = "Bottom Left";
        else if (_lp.X > Width - 100 && _lp.Y < 100)
            text = "Top Right";
        else if (_lp.X > Width - 100 && _lp.Y > Height - 100)
            text = "Bottom Right";

        BeginInvoke(
            (Action)(
                () => 
                {
                    string currentText = _tooltip.GetToolTip(this);
                    if (currentText != text)
                    {
                        _tooltip.SetToolTip(this, text);
                    }
                }
            )
        );
    }
}

答案 1 :(得分:0)

通过取消PopUp事件,您明确阻止ToolTip显示,因为PopUp发生在实际显示ToolTip之前。每当您的表单触发要显示的工具提示时,e.Cancel = true就会被点击

我不确定你对e.Cancel的意图,但我想你只想在文本为空或不在其中一个有效显示区域时将其设置为true。在您的条件链中添加其他其他内容,并将e.Cancel作为全部内容放置,这应该与您想要显示ToolTip的所有区域相对应:

void OnTooltipPopup(object sender, PopupEventArgs e)
{
    string text = null;
    if (_lp.X < 100 && _lp.Y < 100)
        text = "Top Left";
    else if (_lp.X < 100 && _lp.Y > Height - 100)
        text = "Bottom Left";
    else if (_lp.X > Width - 100 && _lp.Y < 100)
        text = "Top Right";
    else if (_lp.X > Width - 100 && _lp.Y > Height - 100)
        text = "Bottom Right";
    else
        e.Cancel = true;

        var existing = _tooltip.GetToolTip(this);
        if (existing == text)
        {
            return;
        }

        if (text != null)
            _tooltip.SetToolTip(this, text); // calls into this method
}

这应该是最简单,最快速的修复方法。

答案 2 :(得分:0)

我认为比你的方法更void OnTooltipPopup(object sender, PopupEventArgs e) 你错过了以下一行

_tooltip.Show(text, _lp);

它应该强制显示工具提示。

另外,为避免计算此方法的位置,请尝试测试从Paint.Drawning的Paint中击中该区域。它在MSDN上的上述链接上进行了描述:msdn