如何防止工具提示在自定义控件中闪烁?

我已经制作了自定义控件,当条件满足时,我想显示一个工具提示:

protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); var plannedItem = GetPlannedItemByPosition(e.Location); if (plannedItem != null) _tooltip.SetToolTip(this, plannedItem.Description); else _tooltip.RemoveAll(); } 

此代码工作正常,除了工具提示闪烁的面孔。

这个自定义控件描绘了OnPaint事件中的所有信息,这可能与它有关吗? 如果是这样,我怎样才能防止工具提示闪烁?

在鼠标光标位置显示工具提示时会发生这种情况。 只要提示窗口出现,Windows就会注意到鼠标位于该窗口中并发布了MouseMove消息。 这使得工具提示消失了。 这使Windows将MouseMove消息发送到您的控件,运行OnMouseMove()方法。 这使得工具提示再次出现。 Etcetera,你会看到工具提示迅速闪烁。

通过以下任何方法解决此问题:

  • 显示工具提示远离鼠标位置,因此它不会与鼠标光标重叠
  • 仅在需要更改时更新/显示工具提示
  • 将控件的Capture属性设置为true,以便工具提示不会获得MouseMove消息

记住最后一个鼠标位置,并仅在鼠标位置发生变化时设置工具提示。

 public partial class Form1 : Form { private int lastX; private int lastY; private void button1_MouseMove(object sender, MouseEventArgs e) { if (eX != this.lastX || eY != this.lastY) { toolTip1.SetToolTip(button1, "test"); this.lastX = eX; this.lastY = eY; } } 

由于这是一个绘制的自定义控件,我认为让变量保持最后显示的提示可能更容易,而不是总是“设置”工具提示,只需显示它。

简单示例(仅使用表单):

 public partial class Form1 : Form { private List _Tips = new List(); private TipRect _LastTip; private ToolTip _tooltip = new ToolTip(); public Form1() { InitializeComponent(); _Tips.Add(new TipRect(new Rectangle(32, 32, 32, 32), "Tip #1")); _Tips.Add(new TipRect(new Rectangle(100, 100, 32, 32), "Tip #2")); } private void Form1_Paint(object sender, PaintEventArgs e) { foreach (TipRect tr in _Tips) e.Graphics.FillRectangle(Brushes.Red, tr.Rect); } private void Form1_MouseMove(object sender, MouseEventArgs e) { TipRect checkTip = GetTip(e.Location); if (checkTip == null) { _LastTip = null; _tooltip.Hide(this); } else { if (checkTip != _LastTip) { _LastTip = checkTip; _tooltip.Show(checkTip.Text, this, e.Location.X + 10, e.Location.Y + 10, 1000); } } } private TipRect GetTip(Point p) { TipRect value = null; foreach (TipRect tr in _Tips) { if (tr.Rect.Contains(p)) value = tr; } return value; } } 

这是我创建的TipRect类,用于模拟PlannedItem类的任何内容:

 public class TipRect { public Rectangle Rect; public string Text; public TipRect(Rectangle r, string text) { Rect = r; Text = text; } } 

我想你的鼠标在你认为它静止时会移动一点。 我建议你在这里做一些缓存 – 如果plannedItem已经改变,只调用_tooltip.SetToolTip。

对于这个线程的访问者,这是我做的,遵循上面的建议(VB.NET):

 Dim LastToolTip As String Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove Dim NewToolTip = CalculateTooltipText(eX, eY) If LastToolTip <> NewToolTip Then ToolTip1.SetToolTip(PictureBox1, NewToolTip) LastToolTip = NewToolTip End If End Sub 

它停止了闪烁。