显示部分用户控件的工具提示

时间:2015-12-12 08:19:37

标签: c# .net

我正在构建将显示切片的自定义控件,例如彩色网格。 我设法做了绘图,滚动和基本逻辑,但我在为每个图块创建工具提示时遇到问题。
每种图块颜色取决于"绑定的数据"那个瓷砖。

enter image description here

我试着描述一下我的想法:
上图显示了我的控制,我在那里绘制了4个方格,当用户悬停我控件的不同部分时,我想显示不同的工具提示。 下面是我的工具提示(小红色矩形),下面是标准的WinForms图表组件 我希望在我的控制中得到这种行为(工具提示无法控制,因此可以正确显示长文本。)

enter image description here

下面是我的控件代码,只有基本功能:

public sealed class UC1 : UserControl
{
    private bool _showTooltip;
    private string _tooltipText;
    private Point _mousePosition;

    public UC1()
    {
        MinimumSize = new Size(100, 100);
        Size = new Size(100, 100);
        SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        e.Graphics.FillRectangle(Brushes.LightGoldenrodYellow, 0, 0, Width/2, Height/2);
        e.Graphics.FillRectangle(Brushes.LightGray, Width/2, 0, Width, Height/2);
        e.Graphics.FillRectangle(Brushes.LightSlateGray, 0, Height/2, Width/2, Height);
        e.Graphics.FillRectangle(Brushes.LightSteelBlue, Width/2, Height/2, Width, Height);

        using (var p = new Pen(Color.Black, 2))
        {
            e.Graphics.DrawLine(p, Width/2, 0, Width/2, Height);
            e.Graphics.DrawLine(p, 0, Height/2, Width, Height/2);
        }

        if (_showTooltip)
        {
            SizeF c = e.Graphics.MeasureString(_tooltipText, DefaultFont);
            int width = (int) c.Width;
            int height = (int) c.Height;
            const int offset = 12;

            var x = _mousePosition.X + width + offset > Width ? _mousePosition.X - width : _mousePosition.X + offset;
            var y = _mousePosition.Y + height + offset > Height ? _mousePosition.Y - height : _mousePosition.Y + offset;

            e.Graphics.FillRectangle(Brushes.Red, x, y, width, height);
            e.Graphics.DrawString(_tooltipText, DefaultFont, Brushes.Black, x, y);
        }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        if (e.X > 0 && e.X < Width/2 && e.Y > 0 && e.Y < Height/2)
        {
            Debug.WriteLine("1,1 square");
            _tooltipText = "1,1";
        }
        else if (e.X > Width/2 && e.X < Width && e.Y > 0 && e.Y < Height/2)
        {
            Debug.WriteLine("1,2 square");
            _tooltipText = "1,2";
        }
        else if (e.X > 0 && e.X < Width/2 && e.Y > Height/2 && e.Y < Height)
        {
            Debug.WriteLine("2,1 square");
            _tooltipText = "2,1";
        }
        else if (e.X > Width/2 && e.X < Width && e.Y > Height/2 && e.Y < Height)
        {
            Debug.WriteLine("2,2 square");
            _tooltipText = "2,2";
        }
        _mousePosition = e.Location;
        _showTooltip = true;
        Refresh();
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        _showTooltip = false;
        Refresh();
        base.OnMouseLeave(e);
    }
}

我发现了类似的问题:How to make a floating (tooltip) control in Windows.Forms?但我想避免创建自定义工具提示,而是使用标准工具提示。

如何在悬停在不同的图块上时显示将更改文本的标准工具提示。我想将所有内容添加到我的用户控件中,因此我不必添加任何代码来托管我的控件。

1 个答案:

答案 0 :(得分:1)

为什么要尝试自己绘制工具提示而不是使用系统工具?

只需在UC课程中添加一个

// private bool _showTooltip;      ?? probably not needed any more..
private string _tooltipText;   
// private Point _mousePosition;   ??..
ToolTip ttip = new ToolTip();

并将其设置为:

// _mousePosition = e.Location; ??..
// _showTooltip = true;         ??..

ttip.SetToolTip(this, _tooltipText);  // use this in the mousemove
Refresh();

当然,现在你可以跳过整个绘画部分..

如果您想控制显示ToolTip的位置,请使用其中一个ShowToolTip()重载而不是SetToolTip() ..!

虽然两者仍然存在,但这是结果,越过UC的边界并显示出漂亮的投影......:

enter image description here

如果您确实希望ToolTip看起来与通常的OwnerDraw不同,可以将true设置为Draw并将其GDI+事件编码,就像任何其他控件一样使用 Point tipLoc = Point.Empty; 图形方法..

<强>更新

存在固有的闪烁问题;有关解释,请参阅Hans' answer here;他的建议#2和其中一个答案很有帮助:

  

记住鼠标的最后位置并仅在鼠标时设置工具提示   职位变动。

所以我们需要添加最后一个ToolTip位置:

if (tipLoc != e.Location )
{
    tipLoc = e.Location;
    ttip.SetToolTip(this, _tooltipText);
}

我们在鼠标移动中测试和设置:

.nodes()