Agregar mensaje WM_MOUSEMOVE en header de listview

Iniciado por Juan Sanchez, 15 Agosto 2016, 18:09 PM

0 Miembros y 1 Visitante están viendo este tema.

Juan Sanchez

Saludos a todos los integrantes del foro, bueno debo acudir a ustedes por un tema que tal ves no es tan necesario.

al parecer el ListView de VB.NET en la vista detalle no genera el mensaje WM_MOUSEMOVE cuando se pasa el mouse sobre las columnas de la cabecera o como se conoce header, y mi pregunta es como puedo agregar a la cola de mensajes de windows al header de listview en vb net para que cuando pase el mouse encima del header me mande ese mensaje.

Código (vbnet) [Seleccionar]
Protected Overrides Sub WndProc(ByRef m As Message)
  If m.Msg = WM_MOUSEMOVE Then
    'Procesar mensaje cuando pase el mouse encima del header del ListView
  End If
  MyBase.WndProc(m)
End Sub


Gracias de antemano por sus respuestas.

Eleкtro

#1
Para empezar a indagar en el asunto, puedes enviar el mensaje LVM_GETHEADER al listview para obtener el handle de la ventana del header y seguidamente obtener rectangle de la ventana con la función GetWindowRectangle, y así al menos conocerás la posición y tamaño del header.

Por mi parte no logro hallar una posible solución, está dificil, me encontré con varias complicaciones y al final desistí, pero quizás con la información que te he proporcionado tu puedas llegar a alguna idea que a mi no se me ocurrió.

Te dejo aquí las definiciones necesarias:
Código (vbnet) [Seleccionar]
<SuppressUnmanagedCodeSecurity>
Friend NotInheritable Class NativeMethods

   Private Sub New()
   End Sub

   <DllImport("user32.dll", SetLastError:=True)>
   Friend Shared Function GetWindowRect(ByVal hwnd As IntPtr,
                                  <Out> ByRef refRc As Rect
   ) As <MarshalAs(UnmanagedType.Bool)> Boolean
   End Function

   <DllImport("user32.dll", SetLastError:=True)>
   Friend Shared Function SendMessage(ByVal hwnd As IntPtr,
                                      ByVal msg As ListViewMessages,
                                      ByVal wParam As IntPtr,
                                      ByVal lParam As IntPtr
   ) As IntPtr
   End Function

   Friend Enum ListViewMessages As Integer

       <Browsable(False)>
       <EditorBrowsable(EditorBrowsableState.Never)>
       First = &H1000 ' LVM_FIRST defined in the Windows SDK file: CommCtrl.h

       GetHeader = (ListViewMessages.First + 31)

   End Enum

   <StructLayout(LayoutKind.Sequential)>
   Friend Structure Rect

       Public Property Left As Integer
       Public Property Top As Integer
       Public Property Right As Integer
       Public Property Bottom As Integer

       Public Sub New(ByVal left As Integer, ByVal top As Integer,
                      ByVal right As Integer, ByVal bottom As Integer)

           Me.Left = left
           Me.Top = top
           Me.Right = right
           Me.Bottom = bottom

       End Sub

       Public Shared Widening Operator CType(rect As Rect) As Rectangle
           Return New Rectangle(rect.Left, rect.Top, (rect.Right - rect.Left), (rect.Bottom - rect.Top))
       End Operator

   End Structure

End Class


Saludos!








Juan Sanchez

Bueno agradezco tu respuesta que siempre es bueno salir de dudas, lo que veo es que el procedimiento
Código (vbnet) [Seleccionar]
Protected Overrides Sub WndProc(ByRef m As Message)
  If m.Msg = WM_MOUSEMOVE Then
    'Este procedimiento quiero que sea del header y no de ListView
  End If
  MyBase.WndProc(m)
End Sub

es de la ventana ListView donde espera todos los mensajes a esa ventana y la ventana o el header es otra entonces se debe esperar casi de la misma forma los mensajes del header, en este caso el header solo envia el mensaje WM_NOTIFY a su ventana padre que es el ListView, no se si estoy equivocado quisiera que me despejen esa duda, y si fuese así como se haría para esperar los mensajes del header al igual que el listview con que apis o funciones se implementaría, leí en la web la API CallWindowProcA y CallWindowProcW pareciera que hacen eso, ahora mi idea se centra en implementar un procedimiento para el header y asi obtener el mensaje WM_MOUSEMOVE y otros como de su ventana padre listview.
Espero que me ayuden con eso, les agradezco por su ayuda, muchas gracias Elektro.

Juan Sanchez

Tambien encontré en la web esta clase para capturar los mensajes de una ventana asignando un handle en el siguiente link https://msdn.microsoft.com/en-us/library/system.windows.forms.nativewindow.assignhandle(v=vs.110).aspx
Código (vbnet) [Seleccionar]
Imports System.Runtime.InteropServices
Friend Class HeaderControl
  Inherits NativeWindow

  <DllImport("user32.dll", EntryPoint:="SendMessage")>
  Private Shared Function SendMessage(hwnd As IntPtr, wMsg As Integer, wParam As IntPtr, lParam As IntPtr) As IntPtr
  End Function

  Private Const LVM_GETHEADER As UInt32 = &H101F
  Private Const WM_MOUSEMOVE As Int32 = &H200

  Public Sub New(LV As ListView)
    'Get handle to LV header
    Dim hWnd_LV_Header As IntPtr = SendMessage(LV.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero)
    If hWnd_LV_Header <> IntPtr.Zero Then
      Me.AssignHandle(hWnd_LV_Header)
      AddHandler LV.HandleDestroyed, AddressOf LV_destroy ' To release handle when LV destroyed?
    End If
  End Sub

  Private Sub LV_destroy(sender As Object, e As EventArgs)
    Me.ReleaseHandle()
  End Sub

  ' subclass LV header...
  Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
    Select Case m.Msg
      Case WM_MOUSEMOVE ' https://msdn.microsoft.com/en-us/library/windows/desktop/ms645616%28v=vs.85%29.aspx
        ' show mouse location over LV column header
        Debug.WriteLine("x={0}, y={1}", m.LParam.ToInt32 And &HFFFF&, m.LParam.ToInt32 \ &H10000 And &HFFFF&) ' http://support.microsoft.com/kb/112651
    End Select
    MyBase.WndProc(m)
  End Sub
End Class

Segun lo que entiendo esta clase escucha todos los mensajes del header de listview, y disculpen mi ignorancia estoy aprendiendo el lenguaje vb net, como integro la clase HeaderControl a mi clase Listview que es la siguiente.
Código (vbnet) [Seleccionar]
Public Class ListView
  Inherits Windows.Forms.ListView

  Public Sub New()
    '
  End Sub

  Protected Overrides Sub WndProc(ByRef m As Message)
    'mensajes de listview
    MyBase.WndProc(m)
  End Sub

End Class


Gracias de antemano