elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Estamos en la red social de Mastodon


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Listview header modificado en listview vbnet
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Listview header modificado en listview vbnet  (Leído 7,966 veces)
Juan Sanchez

Desconectado Desconectado

Mensajes: 14


Ver Perfil
Listview header modificado en listview vbnet
« en: 8 Diciembre 2015, 20:06 pm »

Saludos a todos los componentes de este foro, lo que quiero consultarles es como puedo cambiar el backcolor y forecolor en el header de un listview en vbnet con las apis de windows, se los agradeceré mucho y espero tener suerte...


En línea

Lekim

Desconectado Desconectado

Mensajes: 268



Ver Perfil
Re: Listview header modificado en listview vbnet
« Respuesta #1 en: 12 Diciembre 2015, 18:22 pm »

hola

No entiendo porqué quieres usar API para cambiar el estilo de las cabeceras de un Listview cuando vb.net ya ofrece medios para ello.

ListView.DrawColumnHeader Event



Código
  1. Public Class Form1
  2.    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  3.        ListView1.View = View.Details
  4.        ListView1.Columns.Add("Header1", 100)
  5.        ListView1.Columns.Add("Header2", 100)
  6.        ListView1.Items.Add("Item1")
  7.        ListView1.Items(0).SubItems.Add("SubItem1")
  8.        ListView1.Items.Add("Item2")
  9.        ListView1.Items(1).SubItems.Add("SubItem2")
  10.        ListView1.OwnerDraw = True
  11.  
  12.    End Sub
  13.  
  14.    Private Sub ListView1_DrawColumnHeader(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewColumnHeaderEventArgs) Handles ListView1.DrawColumnHeader
  15.        '//Rectángulos para el Bacground
  16.        Try
  17.            'Rectángulo inferior
  18.            e.Graphics.FillRectangle(Brushes.Black, e.Bounds)
  19.            'Rectángulo superior (Se superpone sobre el rectángulo anterior y es más pequeño)
  20.            Dim RectPoint As New Point(e.Bounds.X + 1, e.Bounds.Y + 1)
  21.            Dim RectSize As New Size(New Point(e.Bounds.Width - 2, e.Bounds.Height - 2))
  22.            Dim Rect As New Rectangle(RectPoint, RectSize)
  23.            e.Graphics.FillRectangle(Brushes.White, Rect)
  24.        Finally
  25.        End Try
  26.  
  27.  
  28.        '//Dibuja el texto (Se superpone a los rectángulos anteriores o imagen de fondo)
  29.        Dim sf As New StringFormat()
  30.        Try
  31.            Select Case e.Header.TextAlign
  32.                Case HorizontalAlignment.Center
  33.                    sf.Alignment = StringAlignment.Center
  34.                Case HorizontalAlignment.Right
  35.                    sf.Alignment = StringAlignment.Far
  36.            End Select
  37.  
  38.            Dim headerFont As New Font("Helvetica", 10, FontStyle.Bold)
  39.            Try
  40.                e.Graphics.DrawString(e.Header.Text, headerFont, Brushes.Black, _
  41.                                      New Point(e.Bounds.X + 5, e.Bounds.Y + 1), sf)
  42.            Finally
  43.                headerFont.Dispose()
  44.            End Try
  45.  
  46.        Finally
  47.            sf.Dispose()
  48.        End Try
  49.  
  50.  
  51.    End Sub
  52.  
  53.    Private Sub ListView1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewItemEventArgs) Handles ListView1.DrawItem
  54.        e.DrawDefault = True
  55.    End Sub
  56. End Class
  57.  

Los cambios se asignan por capas primero estableces lo que sería el 'Background' mediante FillRectangle, si creas otro FillRectangle éste se coloca en la parte superior del anterior en el mismo orden en el que se nombra en el código. Y por último la representación del texto. Si escribes la referéncia al texto antes que aplicar el rectángulo entonces no se verá el texto.

También puedes aplicar una imagen en lugar FillRectangle:

Código
  1.  
  2.   Public Class Form1
  3.    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  4.        ListView1.View = View.Details
  5.        ListView1.Columns.Add("Header1", 100)
  6.        ListView1.Columns.Add("Header2", 100)
  7.        ListView1.Items.Add("Item1")
  8.        ListView1.Items(0).SubItems.Add("SubItem1")
  9.        ListView1.Items.Add("Item2")
  10.        ListView1.Items(1).SubItems.Add("SubItem2")
  11.        ListView1.OwnerDraw = True
  12.  
  13.    End Sub
  14.  
  15.    Private Sub ListView1_DrawColumnHeader(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewColumnHeaderEventArgs) Handles ListView1.DrawColumnHeader
  16.  
  17.        '//Dibuja una imagen
  18.        Dim imagen As Image
  19.        imagen = Image.FromFile("C:\Documents and Settings\Administrador\Mis documentos\columnHeader.png")
  20.        e.Graphics.DrawImage(imagen, e.Bounds)
  21.  
  22.  
  23.        '//Dibuja el texto (Se superpone a los rectángulos anteriores o imagen de fondo)
  24.        Dim sf As New StringFormat()
  25.        Try
  26.            Select Case e.Header.TextAlign
  27.                Case HorizontalAlignment.Center
  28.                    sf.Alignment = StringAlignment.Center
  29.                Case HorizontalAlignment.Right
  30.                    sf.Alignment = StringAlignment.Far
  31.            End Select
  32.  
  33.            Dim headerFont As New Font("Helvetica", 10, FontStyle.Bold)
  34.            Try
  35.                e.Graphics.DrawString(e.Header.Text, headerFont, Brushes.Black, _
  36.                                      New Point(e.Bounds.X + 5, e.Bounds.Y + 1), sf)
  37.            Finally
  38.                headerFont.Dispose()
  39.            End Try
  40.  
  41.        Finally
  42.            sf.Dispose()
  43.        End Try
  44.  
  45.  
  46.    End Sub
  47.  
  48.    Private Sub ListView1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewItemEventArgs) Handles ListView1.DrawItem
  49.        e.DrawDefault = True 'No quitar esto. A no ser que apliques una personalización para este evento. DrawDefault dibujará los valores por defecto.
  50.    End Sub
  51. End Class
  52.  




En línea

Juan Sanchez

Desconectado Desconectado

Mensajes: 14


Ver Perfil
Re: Listview header modificado en listview vbnet
« Respuesta #2 en: 29 Enero 2016, 23:26 pm »

Gracias Lekim por responder a la pregunta, lo que quisiera saber como cambiar el backcolor en el header de la parte derecha del sobrante, es decir que toda la barra del header quede de un solo color.
lo que quiero hacer es que se cambie el backcolor de otro color sin utilizar el evento DrawColumnHeader y sin perder los efectos cuando el mouse pasa por encima, por eso decía si se puede modificar solo el backcolor usando alguna api de windows para eso.

tengo mi código que es lo siguiente, lo repinta toda la barra del header pero lo borra las columnas existentes.

Librerias:
Código
  1. Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As IntPtr, ByVal hwndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
  2.  Private Declare Function GetClientRect Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Integer
  3.  Private Declare Function FillRect Lib "USER32.DLL" (ByVal hDC As Integer, ByRef lpRC As RECT, ByVal hBR As Integer) As Integer
  4.  Private Declare Function CreateSolidBrush Lib "GDI32.DLL" (ByVal crColor As Integer) As Integer
  5.  Private Declare Function DeleteObject Lib "GDI32.DLL" (ByVal hObject As Integer) As Integer
  6.  Private Declare Function GetDC Lib "user32" (ByVal hwnd As IntPtr) As Integer
  7.  Private Structure RECT
  8.    Dim Left As Integer
  9.    Dim Top As Integer
  10.    Dim Right As Integer
  11.    Dim Bottom As Integer
  12.  End Structure
  13.  
  14. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  15.    Dim m_HdrHwnd As IntPtr, x As IntPtr, rt As RECT, hBrush As Integer, dc As Integer
  16.    m_HdrHwnd = FindWindowEx(ListView1.Handle, 0, "SysHeader32", vbNullString)
  17.    x = GetClientRect(m_HdrHwnd, rt)
  18.    dc = GetDC(m_HdrHwnd)
  19.    hBrush = CreateSolidBrush(14563858)
  20.    FillRect(dc, rt, hBrush)
  21.  End Sub


mas o menos quiero algo así como en esta imagen en el siguiente link



Gracias por responderme.
  
« Última modificación: 29 Enero 2016, 23:53 pm por Eleкtro » En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.878



Ver Perfil
Re: Listview header modificado en listview vbnet
« Respuesta #3 en: 30 Enero 2016, 06:04 am »

Es una tarea bastante complicada, incluso recurriendo a P/invokes de la WinAPI.

La zona "sin utilizar" en la derecha de la cabecera de las columnas del Listview forma parte del área NO-cliente de la ventana del control, por ende usando código administrado por ejemplo en el evento DrawColumnHeader solo vas a poder dibujar sobre el área cliente del control, así que tienes que recurrir si o si a las funciones Win32 relacionadas con GDI.

Pero el resultado será sencillamente imperfecto, ya que al tratarse del área no-cliente y como lo estamos tratando de pintar manualmente, Windows no puede determinar cuando se debe redibujar ese área, así que a veces verás como desaparece el color de ese área, ya que con los métodos base de invocadores de eventos del ListView parece no ser suficiente para indicar manualmente cuando se debe redibujar el área no-cliente en los eventos que se suceden en el control (ya que no hay un invocador de evento para controlar cuando se hace click en un separador de columna).

Aquí tienes un ejemplo que escribí, tomatelo como tal...un ejemplo, por que como ya dije esto es imperfecto, notarás como desaparece el color al hacer click sobre un separador de columna, y al redimensionar las columnas;
una solución a lo mencionado sería determinar los handles de ventana (hWnd) de todos los separadores de columnas que existan en el control, y suscribirte a cada una de las ventanas de los separadores, es decir a la función de ventana que procesa sus mensajes (WndProc) para determinar cuando se hace click (mensaje de ventana: WM_LButtonUp y WM_NcLButtonUp ) o cuando se mueve (mensaje de ventana: WM_Move y WM_ExitSizeMove) y en ese momento pintar el area no cliente, pero hacer todo eso es demasiado costoso para satisfacer un simple capricho de pintar esa zona... y aparte, por naturaleza este tipo de hacks en los controles de WinForms tenderán a generar molestos efectos de Flickering.

Código
  1. Imports System
  2. Imports System.ComponentModel
  3. Imports System.Diagnostics
  4. Imports System.Drawing
  5. Imports System.Linq
  6. Imports System.Runtime.InteropServices
  7. Imports System.Security
  8. Imports System.Windows.Forms
  9.  
  10. Public Class ListViewEx : Inherits ListView
  11.  
  12.    <Category("Appearance")>
  13.    <DisplayName("Column-Header BackColor")>
  14.    Public Property ColumnHeaderBackColor As Color
  15.  
  16.    <Category("Appearance")>
  17.    <DisplayName("Column-Header ForeColor")>
  18.    Public Property ColumnHeaderForeColor As Color
  19.  
  20.    <Category("Appearance")>
  21.    <DisplayName("Column-Header Separator Color")>
  22.    Public Property ColumnHeaderSeparatorColor As Color
  23.  
  24.    <Category("Appearance")>
  25.    <DisplayName("Column-Header NonClient-Area Drawing Enabled")>
  26.    Public Property ColumnHeaderNonClientAreaDrawingEnabled As Boolean
  27.  
  28.    Private lastColumnHeaderDrawEventArgs As DrawListViewColumnHeaderEventArgs
  29.    Private ignoreColumnHeaderNonClientAreaDrawing As Boolean
  30.  
  31.    <DebuggerNonUserCode>
  32.    Public Sub New()
  33.  
  34.        Me.ColumnHeaderSeparatorColor = SystemPens.ControlLightLight.Color
  35.        Me.ColumnHeaderBackColor = SystemPens.ControlDarkDark.Color
  36.        Me.ColumnHeaderForeColor = SystemColors.ControlText
  37.  
  38.        MyBase.OwnerDraw = True
  39.  
  40.    End Sub
  41.  
  42.    Protected Overrides Sub OnEnter(e As EventArgs)
  43.        Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
  44.        MyBase.OnEnter(e)
  45.    End Sub
  46.  
  47.    Protected Overrides Sub OnLeave(e As EventArgs)
  48.        Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
  49.        MyBase.OnLeave(e)
  50.    End Sub
  51.  
  52.    Protected Overrides Sub OnGotFocus(e As EventArgs)
  53.        Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
  54.        MyBase.OnGotFocus(e)
  55.    End Sub
  56.  
  57.    Protected Overrides Sub OnLostFocus(e As EventArgs)
  58.        Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
  59.        MyBase.OnLostFocus(e)
  60.    End Sub
  61.  
  62.    Protected Overrides Sub OnInvalidated(e As InvalidateEventArgs)
  63.        Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
  64.        MyBase.OnInvalidated(e)
  65.    End Sub
  66.  
  67.    Protected Overrides Sub OnDrawSubItem(e As DrawListViewSubItemEventArgs)
  68.        Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
  69.        MyBase.OnDrawSubItem(e)
  70.    End Sub
  71.  
  72.    Protected Overrides Sub OnColumnWidthChanging(e As ColumnWidthChangingEventArgs)
  73.        Me.ignoreColumnHeaderNonClientAreaDrawing = True
  74.        MyBase.OnColumnWidthChanging(e)
  75.    End Sub
  76.  
  77.    Protected Overrides Sub OnColumnWidthChanged(e As ColumnWidthChangedEventArgs)
  78.        Me.ignoreColumnHeaderNonClientAreaDrawing = False
  79.        Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
  80.        MyBase.OnColumnWidthChanged(e)
  81.    End Sub
  82.  
  83.    Protected Overrides Sub OnDrawColumnHeader(ByVal e As DrawListViewColumnHeaderEventArgs)
  84.        Me.DrawClientColumnHeader(e)
  85.        MyBase.OnDrawColumnHeader(e)
  86.    End Sub
  87.  
  88.    Protected Overrides Sub OnDrawItem(e As DrawListViewItemEventArgs)
  89.  
  90.        Using g As Graphics = e.Graphics
  91.            e.DrawText()
  92.        End Using
  93.  
  94.        MyBase.OnDrawItem(e)
  95.  
  96.    End Sub
  97.  
  98.    <DebuggerStepThrough>
  99.    Private Sub DrawClientColumnHeader(ByVal e As DrawListViewColumnHeaderEventArgs)
  100.  
  101.        ' If it is the last column...
  102.        If (e.ColumnIndex = (MyBase.Columns.Count - 1)) Then
  103.            Me.lastColumnHeaderDrawEventArgs = e
  104.            Me.DrawNonClientColumnHeader(e)
  105.        End If
  106.  
  107.        e.DrawDefault = False ' Set Owner drawing.
  108.  
  109.        Using g As Graphics = e.Graphics
  110.  
  111.            ' Draw header background.
  112.            Dim bgBounds As Rectangle = e.Bounds
  113.            Using bgBrush As New SolidBrush(Me.ColumnHeaderBackColor)
  114.                g.FillRectangle(bgBrush, bgBounds)
  115.            End Using
  116.  
  117.            ' Measure column separator bounds.
  118.            Dim colBounds As Rectangle = e.Bounds
  119.            colBounds.Width -= 1
  120.            colBounds.Height -= 1
  121.  
  122.            ' Draw column separator.
  123.            Using separatorPen As New Pen(Me.ColumnHeaderSeparatorColor)
  124.                g.DrawRectangle(separatorPen, colBounds)
  125.            End Using
  126.  
  127.            ' Set text formatting.
  128.            Dim flags As TextFormatFlags = TextFormatFlags.VerticalCenter Or TextFormatFlags.EndEllipsis
  129.            Select Case e.Header.TextAlign
  130.                Case HorizontalAlignment.Left
  131.                    flags = (flags Or TextFormatFlags.Left)
  132.                Case HorizontalAlignment.Center
  133.                    flags = (flags Or TextFormatFlags.HorizontalCenter)
  134.                Case Else
  135.                    flags = (flags Or TextFormatFlags.Right)
  136.            End Select
  137.  
  138.            ' Measure and draw text.
  139.            Dim width As Integer = TextRenderer.MeasureText(" ", e.Font).Width
  140.            Dim txtBounds As Rectangle = Rectangle.Inflate(e.Bounds, -width, 0)
  141.            TextRenderer.DrawText(g, e.Header.Text, e.Font, txtBounds, Me.ColumnHeaderForeColor, flags)
  142.  
  143.        End Using
  144.  
  145.    End Sub
  146.  
  147.    <DebuggerStepThrough>
  148.    Private Sub DrawNonClientColumnHeader(ByVal e As DrawListViewColumnHeaderEventArgs)
  149.  
  150.        If (Me.ColumnHeaderNonClientAreaDrawingEnabled) AndAlso Not (Me.ignoreColumnHeaderNonClientAreaDrawing) AndAlso
  151.           (e IsNot Nothing) Then
  152.  
  153.            Dim lv As ListView = e.Header.ListView
  154.            Dim hwnd As IntPtr = Me.GetColumnHeaderHwnd(lv)
  155.            Dim hdc As IntPtr = NativeMethods.GetDC(hwnd)
  156.            Dim headersWidth As Integer =
  157.                (From col As ColumnHeader In MyBase.Columns.Cast(Of ColumnHeader)()
  158.                 Select col.Width
  159.                ).Sum
  160.  
  161.            Using g As Graphics = Graphics.FromHdc(hdc)
  162.  
  163.                Dim rect As New Rectangle(e.Bounds.Right + 1, e.Bounds.Top, (Me.Bounds.Width - headersWidth), e.Bounds.Height)
  164.  
  165.                Using bgBrush As New SolidBrush(Me.ColumnHeaderBackColor)
  166.                    g.FillRectangle(bgBrush, rect)
  167.                End Using
  168.  
  169.            End Using
  170.  
  171.            NativeMethods.ReleaseDC(hwnd, hdc)
  172.  
  173.        End If
  174.  
  175.    End Sub
  176.  
  177.    <DebuggerStepThrough>
  178.    Private Function GetColumnHeaderHwnd(ByVal lv As ListView) As IntPtr
  179.        Return NativeMethods.SendMessage(lv.Handle, NativeMethods.LvmGetHeader, New IntPtr(0), New IntPtr(0))
  180.    End Function
  181.  
  182. End Class
  183.  
  184. Friend NotInheritable Class NativeMethods
  185.  
  186.    ' https://msdn.microsoft.com/en-us/library/windows/desktop/bb774937%28v=vs.85%29.aspx
  187.    Friend Const LvmGetHeader As Integer = &H101F
  188.  
  189.    ' https://msdn.microsoft.com/en-us/library/windows/desktop/dd144871(v=vs.85).aspx
  190.    <SuppressUnmanagedCodeSecurity>
  191.    <DllImport("user32", SetLastError:=True)>
  192.    Friend Shared Function GetDC(
  193.           ByVal hwnd As IntPtr
  194.    ) As IntPtr
  195.    End Function
  196.  
  197.    ' https://msdn.microsoft.com/en-us/library/windows/desktop/dd162920(v=vs.85).aspx
  198.    <SuppressUnmanagedCodeSecurity>
  199.    <DllImport("user32", SetLastError:=True)>
  200.    Friend Shared Function ReleaseDC(
  201.           ByVal hwnd As IntPtr,
  202.           ByVal hdc As IntPtr
  203.    ) As IntPtr
  204.    End Function
  205.  
  206.    ' https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx
  207.    <SuppressUnmanagedCodeSecurity>
  208.    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
  209.    Friend Shared Function SendMessage(
  210.           ByVal hwnd As IntPtr,
  211.           ByVal msg As UInteger,
  212.           ByVal wParam As IntPtr,
  213.           ByVal lParam As IntPtr
  214.    ) As IntPtr
  215.    End Function
  216.  
  217. End Class
  218.  

PD: Nótese que me faltó añadir un Getter/Setter a las propiedades para llamar a los métodos que pintan sobre la cabecera de las columnas cuando se modifica el valor de dichas propiedades.

Saludos
« Última modificación: 30 Enero 2016, 07:02 am por Eleкtro » En línea



Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
listview
Programación Visual Basic
visualfree 3 2,430 Último mensaje 10 Octubre 2006, 19:50 pm
por CeLaYa
ListView
.NET (C#, VB.NET, ASP)
RCB 0 2,517 Último mensaje 15 Abril 2010, 02:24 am
por RCB
Listview
Java
Maik33 2 2,807 Último mensaje 10 Julio 2012, 08:50 am
por Maik33
Agregar mensaje WM_MOUSEMOVE en header de listview
.NET (C#, VB.NET, ASP)
Juan Sanchez 3 3,610 Último mensaje 21 Agosto 2016, 04:34 am
por Juan Sanchez
MOVIDO: Agregar mensaje WM_MOUSEMOVE en header de listview
Programación Visual Basic
Eleкtro 0 2,749 Último mensaje 15 Agosto 2016, 22:00 pm
por Eleкtro
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines