如何为列表框中的每个项目设置不同的工具提示文本? [英] How can I set different Tooltip text for each item in a listbox?

查看:18
本文介绍了如何为列表框中的每个项目设置不同的工具提示文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数据绑定到对象集合的列表框.列表框被配置为显示每个对象的标识符属性.我想显示一个工具提示,其中包含悬停在​​列表框中的项目的特定信息,而不是整个列表框的一个工具提示.

I have a listbox that is databound to a Collection of objects. The listbox is configured to display an identifier property of each object. I would like to show a tooltip with information specific to the item within the listbox that is being hovered over rather than one tooltip for the listbox as a whole.

我在 WinForms 中工作,感谢一些有用的博客文章,我想分享一个非常好的解决方案.

I am working within WinForms and thanks to some helpful blog posts put together a pretty nice solution, which I wanted to share.

我有兴趣看看是否有任何其他优雅的解决方案可以解决这个问题,或者如何在 WPF 中完成.

I'd be interested in seeing if there's any other elegant solutions to this problem, or how this may be done in WPF.

推荐答案

为了解决这个问题,有两个主要的子问题必须解决:

There are two main sub-problems one must solve in order to solve this problem:

  1. 确定悬停在哪个项目上
  2. 当用户将鼠标悬停在一个项目上时触发 MouseHover 事件,然后在列表框中移动光标并将鼠标悬停在另一个项目上.

第一个问题很容易解决.通过在 MouseHover 的处理程序中调用如下所示的方法,您可以确定鼠标悬停在哪个项目上:

The first problem is rather simple to solve. By calling a method like the following within your handler for MouseHover, you can determine which item is being hovered over:

private ITypeOfObjectsBoundToListBox DetermineHoveredItem()
{
    Point screenPosition = ListBox.MousePosition;
    Point listBoxClientAreaPosition = listBox.PointToClient(screenPosition);

    int hoveredIndex = listBox.IndexFromPoint(listBoxClientAreaPosition);
    if (hoveredIndex != -1)
    {
        return listBox.Items[hoveredIndex] as ITypeOfObjectsBoundToListBox;
    }
    else
    {
        return null;
    }
}

然后根据需要使用返回值设置工具提示.

Then use the returned value to set the tool-tip as needed.

第二个问题是通常鼠标悬停事件不会再次触发,直到光标离开控件的客户区然后又回来.

The second problem is that normally the MouseHover event isn't fired again until the cursor has left the client area of the control and then come back.

您可以通过包装 TrackMouseEvent Win32API 调用来解决此问题.
在以下代码中,ResetMouseHover 方法包装了 API 调用以获得所需的效果:重置控制悬停事件触发时间的底层计时器.

You can get around this by wrapping the TrackMouseEvent Win32API call.
In the following code, the ResetMouseHover method wraps the API call to get the desired effect: reset the underlying timer that controls when the hover event is fired.

public static class MouseInput
{
    // TME_HOVER
    // The caller wants hover notification. Notification is delivered as a 
    // WM_MOUSEHOVER message.  If the caller requests hover tracking while 
    // hover tracking is already active, the hover timer will be reset.

    private const int TME_HOVER = 0x1;

    private struct TRACKMOUSEEVENT
    {
        // Size of the structure - calculated in the constructor
        public int cbSize;

        // value that we'll set to specify we want to start over Mouse Hover and get
        // notification when the hover has happened
        public int dwFlags;

        // Handle to what's interested in the event
        public IntPtr hwndTrack;

        // How long it takes for a hover to occur
        public int dwHoverTime;

        // Setting things up specifically for a simple reset
        public TRACKMOUSEEVENT(IntPtr hWnd)
        {
            this.cbSize = Marshal.SizeOf(typeof(TRACKMOUSEEVENT));
            this.hwndTrack = hWnd;
            this.dwHoverTime = SystemInformation.MouseHoverTime;
            this.dwFlags = TME_HOVER;
        }
    }

    // Declaration of the Win32API function
    [DllImport("user32")]
    private static extern bool TrackMouseEvent(ref TRACKMOUSEEVENT lpEventTrack);

    public static void ResetMouseHover(IntPtr windowTrackingMouseHandle)
    {
        // Set up the parameter collection for the API call so that the appropriate
        // control fires the event
        TRACKMOUSEEVENT parameterBag = new TRACKMOUSEEVENT(windowTrackingMouseHandle);

        // The actual API call
        TrackMouseEvent(ref parameterBag);
    }
}

包装器就位后,您只需在 MouseHover 处理程序的末尾调用 ResetMouseHover(listBox.Handle),即使光标停留在控件的边界内,悬停事件也会再次触发.

With the wrapper in place, you can simply call ResetMouseHover(listBox.Handle) at the end of your MouseHover handler and the hover event will fire again even when the cursor stays within the control's bounds.

我确信这种方法,将所有代码粘贴在 MouseHover 处理程序中一定会导致比实际需要更多的 MouseHover 事件触发,但它会完成工作.欢迎任何改进.

I'm sure this approach, sticking all the code in the MouseHover handler must result in more MouseHover events firing than are really necessary, but it'll get the job done. Any improvements are more than welcome.

这篇关于如何为列表框中的每个项目设置不同的工具提示文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆