Imports System
Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Drawing
Imports System.Linq
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.Windows.Forms
Public Class ListViewEx : Inherits ListView
<Category("Appearance")>
<DisplayName("Column-Header BackColor")>
Public Property ColumnHeaderBackColor As Color
<Category("Appearance")>
<DisplayName("Column-Header ForeColor")>
Public Property ColumnHeaderForeColor As Color
<Category("Appearance")>
<DisplayName("Column-Header Separator Color")>
Public Property ColumnHeaderSeparatorColor As Color
<Category("Appearance")>
<DisplayName("Column-Header NonClient-Area Drawing Enabled")>
Public Property ColumnHeaderNonClientAreaDrawingEnabled As Boolean
Private lastColumnHeaderDrawEventArgs As DrawListViewColumnHeaderEventArgs
Private ignoreColumnHeaderNonClientAreaDrawing As Boolean
<DebuggerNonUserCode>
Public Sub New()
Me.ColumnHeaderSeparatorColor = SystemPens.ControlLightLight.Color
Me.ColumnHeaderBackColor = SystemPens.ControlDarkDark.Color
Me.ColumnHeaderForeColor = SystemColors.ControlText
MyBase.OwnerDraw = True
End Sub
Protected Overrides Sub OnEnter(e As EventArgs)
Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
MyBase.OnEnter(e)
End Sub
Protected Overrides Sub OnLeave(e As EventArgs)
Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
MyBase.OnLeave(e)
End Sub
Protected Overrides Sub OnGotFocus(e As EventArgs)
Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
MyBase.OnGotFocus(e)
End Sub
Protected Overrides Sub OnLostFocus(e As EventArgs)
Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
MyBase.OnLostFocus(e)
End Sub
Protected Overrides Sub OnInvalidated(e As InvalidateEventArgs)
Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
MyBase.OnInvalidated(e)
End Sub
Protected Overrides Sub OnDrawSubItem(e As DrawListViewSubItemEventArgs)
Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
MyBase.OnDrawSubItem(e)
End Sub
Protected Overrides Sub OnColumnWidthChanging(e As ColumnWidthChangingEventArgs)
Me.ignoreColumnHeaderNonClientAreaDrawing = True
MyBase.OnColumnWidthChanging(e)
End Sub
Protected Overrides Sub OnColumnWidthChanged(e As ColumnWidthChangedEventArgs)
Me.ignoreColumnHeaderNonClientAreaDrawing = False
Me.DrawNonClientColumnHeader(Me.lastColumnHeaderDrawEventArgs)
MyBase.OnColumnWidthChanged(e)
End Sub
Protected Overrides Sub OnDrawColumnHeader(ByVal e As DrawListViewColumnHeaderEventArgs)
Me.DrawClientColumnHeader(e)
MyBase.OnDrawColumnHeader(e)
End Sub
Protected Overrides Sub OnDrawItem(e As DrawListViewItemEventArgs)
Using g As Graphics = e.Graphics
e.DrawText()
End Using
MyBase.OnDrawItem(e)
End Sub
<DebuggerStepThrough>
Private Sub DrawClientColumnHeader(ByVal e As DrawListViewColumnHeaderEventArgs)
' If it is the last column...
If (e.ColumnIndex = (MyBase.Columns.Count - 1)) Then
Me.lastColumnHeaderDrawEventArgs = e
Me.DrawNonClientColumnHeader(e)
End If
e.DrawDefault = False ' Set Owner drawing.
Using g As Graphics = e.Graphics
' Draw header background.
Dim bgBounds As Rectangle = e.Bounds
Using bgBrush As New SolidBrush(Me.ColumnHeaderBackColor)
g.FillRectangle(bgBrush, bgBounds)
End Using
' Measure column separator bounds.
Dim colBounds As Rectangle = e.Bounds
colBounds.Width -= 1
colBounds.Height -= 1
' Draw column separator.
Using separatorPen As New Pen(Me.ColumnHeaderSeparatorColor)
g.DrawRectangle(separatorPen, colBounds)
End Using
' Set text formatting.
Dim flags As TextFormatFlags = TextFormatFlags.VerticalCenter Or TextFormatFlags.EndEllipsis
Select Case e.Header.TextAlign
Case HorizontalAlignment.Left
flags = (flags Or TextFormatFlags.Left)
Case HorizontalAlignment.Center
flags = (flags Or TextFormatFlags.HorizontalCenter)
Case Else
flags = (flags Or TextFormatFlags.Right)
End Select
' Measure and draw text.
Dim width As Integer = TextRenderer.MeasureText(" ", e.Font).Width
Dim txtBounds As Rectangle = Rectangle.Inflate(e.Bounds, -width, 0)
TextRenderer.DrawText(g, e.Header.Text, e.Font, txtBounds, Me.ColumnHeaderForeColor, flags)
End Using
End Sub
<DebuggerStepThrough>
Private Sub DrawNonClientColumnHeader(ByVal e As DrawListViewColumnHeaderEventArgs)
If (Me.ColumnHeaderNonClientAreaDrawingEnabled) AndAlso Not (Me.ignoreColumnHeaderNonClientAreaDrawing) AndAlso
(e IsNot Nothing) Then
Dim lv As ListView = e.Header.ListView
Dim hwnd As IntPtr = Me.GetColumnHeaderHwnd(lv)
Dim hdc As IntPtr = NativeMethods.GetDC(hwnd)
Dim headersWidth As Integer =
(From col As ColumnHeader In MyBase.Columns.Cast(Of ColumnHeader)()
Select col.Width
).Sum
Using g As Graphics = Graphics.FromHdc(hdc)
Dim rect As New Rectangle(e.Bounds.Right + 1, e.Bounds.Top, (Me.Bounds.Width - headersWidth), e.Bounds.Height)
Using bgBrush As New SolidBrush(Me.ColumnHeaderBackColor)
g.FillRectangle(bgBrush, rect)
End Using
End Using
NativeMethods.ReleaseDC(hwnd, hdc)
End If
End Sub
<DebuggerStepThrough>
Private Function GetColumnHeaderHwnd(ByVal lv As ListView) As IntPtr
Return NativeMethods.SendMessage(lv.Handle, NativeMethods.LvmGetHeader, New IntPtr(0), New IntPtr(0))
End Function
End Class
Friend NotInheritable Class NativeMethods
' https://msdn.microsoft.com/en-us/library/windows/desktop/bb774937%28v=vs.85%29.aspx
Friend Const LvmGetHeader As Integer = &H101F
' https://msdn.microsoft.com/en-us/library/windows/desktop/dd144871(v=vs.85).aspx
<SuppressUnmanagedCodeSecurity>
<DllImport("user32", SetLastError:=True)>
Friend Shared Function GetDC(
ByVal hwnd As IntPtr
) As IntPtr
End Function
' https://msdn.microsoft.com/en-us/library/windows/desktop/dd162920(v=vs.85).aspx
<SuppressUnmanagedCodeSecurity>
<DllImport("user32", SetLastError:=True)>
Friend Shared Function ReleaseDC(
ByVal hwnd As IntPtr,
ByVal hdc As IntPtr
) As IntPtr
End Function
' https://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx
<SuppressUnmanagedCodeSecurity>
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Friend Shared Function SendMessage(
ByVal hwnd As IntPtr,
ByVal msg As UInteger,
ByVal wParam As IntPtr,
ByVal lParam As IntPtr
) As IntPtr
End Function
End Class