How to set tooltips on ListView Subitems in .Net

后端 未结 5 1265
轻奢々
轻奢々 2021-02-10 09:15

I am trying to set the tool tip text for some of my subitems in my listview control. I am unable to get the tool tip to show up.

Anyone have any suggestions?

         


        
相关标签:
5条回答
  • 2021-02-10 09:19

    ObjectListView (an open source wrapper around .NET WinForms ListView) has builtin support for cell tooltips (and, yes, it does work with VB). You listen for a CellToolTip event and you can do things like this (which is admittedly excessive):

    If you don't want to use ObjectListView, you need to subclass ListView, listen for WM_NOTIFY messages, and then within those, respond to TTN_GETDISPINFO notifications, in a manner similar to this:

    case TTN_GETDISPINFO:
        ListViewHitTestInfo info = this.HitTest(this.PointToClient(Cursor.Position));
        if (info.Item != null && info.SubItem != null) {
            // Call some method of your own to get the tooltip you want
            String tip = this.GetCellToolTip(info.Item, info.SubItem); 
            if (!String.IsNullOrEmpty(tip)) {
                NativeMethods.TOOLTIPTEXT ttt = (NativeMethods.TOOLTIPTEXT)m.GetLParam(typeof(NativeMethods.TOOLTIPTEXT));
                ttt.lpszText = tip;
                if (this.RightToLeft == RightToLeft.Yes)
                    ttt.uFlags |= 4;
                Marshal.StructureToPtr(ttt, m.LParam, false);
                return; // do not do normal processing
            }
        }
        break;
    

    Obviously, this is C#, not VB, but you get the idea.

    0 讨论(0)
  • 2021-02-10 09:23

    Assuming .NET 2.0 or later, you can also set ListView.ShowItemToolTips to true. If you need to customize the tooltip text for a given item, set ListViewItem.ToolTipText to the string you want displayed.

    0 讨论(0)
  • 2021-02-10 09:28

    If you set ShowItemTooltips for the ListView control in "details" mode and do nothing else, the ListView control will automatically provide tooltips for items and subitems that exceed their column's widths. This turns out to work even if the FullRowSelect property is set to true. If ToolTipText has been set for a ListViewItem and FullRowSelect is true, then the tooltip will appear for the whole row; that's the case where tooltips won't be displayed for subitems.

    0 讨论(0)
  • 2021-02-10 09:28

    You can use the MouseMove event:

    private void listview1_MouseMove(object sender, MouseEventargs e)
    {
        ListViewItem item = listview1.GetItemAt(e.X, e.Y);
        ListViewHitTestInfo info = listview1.HitTest(e.X, e.Y);
        if((item != null) && (info.SubItem != null))
        {
            toolTip1.SetToolTip(listview1, info.SubItem.Text);
        }
        else
        {
            toolTip1.SetToolTip(listview1, "");
        }
    }
    
    0 讨论(0)
  • 2021-02-10 09:41

    The original code in the question does not work since it creates a New ToolTip inside OnMouseMove. I guess that the ToolTip.Show method is asynchronous and thus the function exits immediately after invoking it, destroying the temporary ToolTip. When Show gets to execute, the object does not exist anymore.

    The solution would be to create a persistent ToolTip object, by:

    1. a ToolTip control on the form; or
    2. a private ToolTip class field (disposed in the Finalize or Dispose method of the class); or
    3. a Static object inside the function.

    Also, there is no need to GetItemAt() since ListViewHitTestInfo already contains both the item and subitem references.
    Improving Colin's answer, here is my code:

    Private Sub ListView_MouseMove(sender As Object, e As MouseEventArgs) _
    Handles MyList1.MouseMove
        Static prevMousePos As Point = New Point(-1, -1)
    
        Dim lv As ListView = TryCast(sender, ListView)
        If lv Is Nothing Then _
            Exit Sub
        If prevMousePos = MousePosition Then _
            Exit Sub  ' to avoid annoying flickering
    
        With lv.HitTest(lv.PointToClient(MousePosition))
            If .SubItem IsNot Nothing AndAlso Not String.IsNullOrEmpty(.SubItem.Text) Then
                'AndAlso .Item.SubItems.IndexOf(.SubItem) = 1
                '...when a specific Column is needed
    
                Static t As ToolTip = toolTip1  ' using a form's control
                'Static t As New ToolTip()      ' using a private variable
                t.ShowAlways = True
                t.UseFading = True
                ' To display at exact mouse position:
                t.Show(.SubItem.Tag, .Item.ListView, _
                       .Item.ListView.PointToClient(MousePosition), 2000)
                ' To display beneath the list subitem:
                t.Show(.SubItem.Tag, .Item.ListView, _
                       .SubItem.Bounds.Location + New Size(7, .SubItem.Bounds.Height + 1), 2000)
                ' To display beneath mouse cursor, as Windows does:
                ' (size is hardcoded in ugly manner because there is no easy way to find it)
                t.Show(.SubItem.Tag, .Item.ListView, _
                       .Item.ListView.PointToClient(Cursor.Position + New Size(1, 20)), 2000)
            End If
            prevMousePos = MousePosition
        End With        
    End Sub
    

    I've made the code as general as possible so that the function could be assigned to multiple ListViews.

    0 讨论(0)
提交回复
热议问题