【问题标题】:Show ToolTips on ListView first row in Framework 4.0在框架 4.0 的 ListView 第一行上显示工具提示
【发布时间】:2015-03-02 14:52:49
【问题描述】:

我有一个使用 VB.Net 在 Framework 2.0 中开发的 WinForm 应用程序,它在所有 ListView 对象上使用事件 MouseMove 来在 ListViews 的第一行显示 ToolTip 文本 - 因为这是不可能的据我所知,在没有第三方工具的情况下在 ColumnHeader 上有工具提示。

问题在于,自从我将应用程序转换为 Framework 4.0 后,这个“技巧”不起作用,并且不再显示工具提示。

有谁知道在 ListView ColumnHeaders 上显示工具提示的解决方案,或者更好的方法?

这是我的代码 sn-p:

Private Sub ShowTooltip(ByVal sender As Object, ByVal e As MouseEventArgs) 
    Handles myListView.MouseMove
  Dim iColumn As System.Int32 = FindListViewColumnHeader(e.X, e.Y)
  If Me.myListView.Columns.Count > 0 AndAlso iColumn >= 0 AndAlso
     iColumn <= Me.myListView.Columns.Count - 1 Then
         Me.myToolTip.Active = True
         Me.myToolTip.UseAnimation = True
         Me.myToolTip.UseFading = True
         Me.myToolTip.AutomaticDelay = 10000
         Me.myToolTip.AutoPopDelay = 10000
         Me.myToolTip.InitialDelay = 0
         Me.myToolTip.ReshowDelay = 2000

         Dim sTooltipText As System.String = SomeText(...)
         If sTooltipText <> DirectCast(Me.myToolTip.Tag, System.String) Then
                 Me.myToolTip.Tag = sTooltipText
                 Me.myToolTip.SetToolTip(Me.myListView, sTooltipText)
         End If
  Else
         Me.myToolTip.Active = False
  End If
End Sub

Protected Overridable Function FindListViewColumnHeader(ByVal X As System.Int32, 
       ByVal Y As System.Int32) As System.Int32
   If Y > 20 And Y < 40 Then
       Dim iCount As System.Int32
       Dim iLeft As System.Int32
       For iCount = 0 To myListView.Columns.Count - 1
           iLeft = iLeft + myListView.Columns(iCount).Width
           If X <= iLeft Then
               Return iCount
               Exit For
           End If
       Next
       Return iCount
   Else
       Return -1
   End If
End Function

注意:myToolTip 是

Friend WithEvents myToolTip As System.Windows.Forms.ToolTip

而 myListView 是

Protected WithEvents myListView As System.Windows.Forms.ListView

请注意,正如问题中所建议的: How to set tooltip for a ListviewItem、ShowItemToolTips 已设置为 True。

【问题讨论】:

  • A ColumnHeader 不会生成 MouseMove 或 MouseHover 类型的事件,因此即使 LV 也不知道鼠标在标题部分。事实上,如果您查看对象浏览器,它的唯一事件是Disposed。 ToolTip 提供程序在ColumnHeader 上不起作用,所以我想知道ToolTipText() 是什么? ListViewItems 具有该属性,但没有标题。 lsRecords 也是个谜
  • @Plutonix 代码我认为是可疑的。什么是 lsRecords?看起来应该是 myListView。
  • 我更正了代码 sn-p,lsRecords 是一个错误。我的问题是 Framework 4.0 ToolTips 也不适用于 ListViewItems。
  • LVI 有自己的内置 ToolTipText 属性。我看不出它是如何工作的:DirectCast(Me.myListView.Columns(iColumn), ColumnHeader).ToolTipText() 无法编译,因为ColumnHeader 上没有ToolTipText
  • 提供的代码不会在 NET 2.0 中的列标题上显示工具提示。它会在一个项目或子项目上立即显示一个,但当您将鼠标移到标题上时它会立即消失。

标签: vb.net winforms listview columnheader


【解决方案1】:

您可以获取标题列的句柄并将其子类化:

<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal newProc As Win32WndProc) As IntPtr

End Function

<DllImport("user32.dll")> _
Private Shared Function CallWindowProc(lpPrevWndFunc As IntPtr, hWnd As IntPtr, Msg As UInteger, wParam As Integer, lParam As Integer) As Integer
End Function

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
End Function

Private Delegate Function Win32WndProc(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

Private Const GWL_WNDPROC As Integer = -4
Private Const WM_LBUTTONDOWN As Integer = &H201
Private Const WM_MOUSEMOVE As Integer = &H200

Private oldWndProc As IntPtr = IntPtr.Zero
Private newWndProc As Win32WndProc = Nothing

Private Sub SubclassHWnd(ByVal hWnd As IntPtr)
    'hWnd is the window you want to subclass...,
    'create a new delegate for the new wndproc
    newWndProc = New Win32WndProc(AddressOf MyWndProc)
    'subclass
    oldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, newWndProc)
End Sub

Private Function MyWndProc(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Select Case Msg
        Case WM_LBUTTONDOWN
            'The lower 2 bytes of lParam are the x coordinate 
            'and the higher 2 bytes the y.
            ToolTip1.Show("My tooltip", ListView1, lParam And &HFFFF, (lParam >> 16) And &HFF, 2000)
            Exit Select
        Case Else
            Exit Select
    End Select

    Return CallWindowProc(oldWndProc, hWnd, Msg, wParam, lParam)
End Function

要对标头进行子类化,请使用:

    'LVM_GETHEADER = &H101F
    Dim hwndHeader As IntPtr = SendMessage(ListView1.Handle, &H101F, 0, 0)
    SubclassHWnd(hwndHeader)

为方便起见,我使用了WM_LBUTTONDOWN 事件。您可以使用WM_MOUSEMOVE 事件并检查鼠标所在的列等...并显示工具提示

子类化代码:Subclass an Unmanged Window in C#

【讨论】:

  • 您的解决方案效果很好,谢谢!我刚刚做了一个小修正以正确读取 x 坐标:lParam And &HFFFF。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-15
  • 1970-01-01
  • 2012-06-18
  • 2012-07-17
  • 1970-01-01
相关资源
最近更新 更多