简体   繁体   中英

How to prevent tooltip from flickering in custom control?

I have made a custom control and when a condition is met, I want to show a tooltip:

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();
}

This code works fine, excepts for the face that the tooltip flickers.

This custom control, paints all the information in the OnPaint event, maybe this has something to do with it? And if it does, how can I prevent the tooltip from flickering?

Remember last mouse position and set the tooltip only when the mouse position changes.

public partial class Form1 : Form
{
    private int lastX;
    private int lastY;

    private void button1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.X != this.lastX || e.Y != this.lastY)
        {
            toolTip1.SetToolTip(button1, "test");

            this.lastX = e.X;
            this.lastY = e.Y;
        }

    }

This will happen when you display the tooltip at the mouse cursor position. As soon as the tip window shows up, Windows notices that the mouse is located in that window and posts a MouseMove message. Which makes the tooltip disappear. Which makes Windows send a MouseMove message to your control, running your OnMouseMove() method. Which makes the tooltip appear again. Etcetera, you'll see the tooltip rapidly flickering.

Solve this by any of the following methods:

  • show the tooltip well away from the mouse position so it won't overlap the mouse cursor
  • only update/show the tooltip when it needs to be changed
  • set the control's Capture property to true so the tooltip won't get a MouseMove message

Since this is a painted custom control, I think it might be easier to just have a variable hold the last shown tip, and instead of always "setting" the tooltip, just show it.

Simple example (using just a form):

public partial class Form1 : Form {
  private List<TipRect> _Tips = new List<TipRect>();
  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;
  }
}

Here is the TipRect class I created to simulate whatever your PlannedItem class is:

public class TipRect {
  public Rectangle Rect;
  public string Text;

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

For the visitors of this thread, here is what I did, following suggestions above (VB.NET):

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

It stopped the flickering.

c# (works on tooltip chart):

Point mem = new Point();
private void xxx_MouseMove(MouseEventArgs e){
    // start
    Point pos = e.Location;
    if (pos == mem) { return; }

    // your code here

    // end
    mem = pos
}

I imagine your mouse does move a little when you think it is still. I suggest you do some kind of caching here - only call _tooltip.SetToolTip if the plannedItem has changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM