简体   繁体   English

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

[英]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?这个自定义控件,绘制了OnPaint事件中的所有信息,也许这与它有关? 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.提示窗口一出现,Windows 就会注意到鼠标位于该窗口中并发布 MouseMove 消息。 Which makes the tooltip disappear.这使工具提示消失。 Which makes Windows send a MouseMove message to your control, running your OnMouseMove() method.这使得 Windows 向您的控件发送 MouseMove 消息,运行您的 OnMouseMove() 方法。 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将控件的 Capture 属性设置为 true,这样工具提示就不会收到 MouseMove 消息

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:这是我创建的用于模拟 PlannedItem 类的 TipRect 类:

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):对于该线程的访问者,这是我按照上面的建议(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): c#(适用于工具提示图表):

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.我建议你在这里做一些缓存——如果plannedItem已经改变,只调用_tooltip.SetToolTip。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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