
Const HDI_FORMAT As Int32 = 4
Const HDI_IMAGE As Int32 = 32
Const HDF_LEFT As Int32 = 0
Const HDF_RIGHT As Int32 = 1
Const HDF_CENTER As Int32 = 2
Const HDF_STRING As Int32 = 16384
Const HDF_BITMAP_ON_RIGHT As Int32 = 4096
Const HDF_IMAGE As Int32 = 2048
Const HDF_SORTUP As Int32 = 1024
Const HDF_SORTDOWN As Int32 = 512
Const LVM_FIRST As Int32 = 4096
Const LVM_GETHEADER As Int32 = LVM_FIRST + 31
Const HDM_FIRST As Int32 = 4608
Const HDM_SETIMAGELIST As Int32 = HDM_FIRST + 8
Const HDM_SETITEM As Int32 = HDM_FIRST + 12
Public Sub ShowHeaderIcon(ByVal list As ListView, ByVal columnIndex As Integer, ByVal sortOrder As SortOrder)
If columnIndex < 0 OrElse columnIndex >= list.Columns.Count Then
Return
End If
Dim hHeader As IntPtr = SendMessage(list.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero)
Dim colHdr As ColumnHeader = list.Columns(columnIndex)
Dim hd As HDITEM = New HDITEM
hd.mask = HDI_IMAGE Or HDI_FORMAT
Dim align As HorizontalAlignment = colHdr.TextAlign
If align = HorizontalAlignment.Left Then
hd.fmt = HDF_LEFT Or HDF_STRING Or HDF_BITMAP_ON_RIGHT
Else
If align = HorizontalAlignment.Center Then
hd.fmt = HDF_CENTER Or HDF_STRING Or HDF_BITMAP_ON_RIGHT
Else
hd.fmt = HDF_RIGHT Or HDF_STRING
End If
End If
If Not (sortOrder = sortOrder.None) Then
hd.fmt = hd.fmt Or (HDF_IMAGE)
End If
hd.iImage = CType(sortOrder, Integer) - 1
SendMessage(hHeader, HDM_SETITEM, New IntPtr(columnIndex), hd)
End Sub
Public Sub SetHeaderImageList(ByVal list As ListView)
Dim hHeader As IntPtr = SendMessage(list.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero)
SendMessage(hHeader, HDM_SETIMAGELIST, IntPtr.Zero, m_imgList.Handle)
End Sub
Shared Function SendMessage(ByVal Handle As IntPtr, ByVal msg As Int32, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function
Shared Function SendMessage(ByVal Handle As IntPtr, ByVal msg As Int32, ByVal wParam As IntPtr, ByRef lParam As HDITEM) As IntPtr
End Function
Private m_imgList As ImageList
Public Sub New()
m_imgList = New ImageList
m_imgList.ImageSize = New Size(8, 8)
m_imgList.TransparentColor = System.Drawing.Color.Magenta
m_imgList.Images.Add(GetArrowBitmap(ArrowType.Ascending))
m_imgList.Images.Add(GetArrowBitmap(ArrowType.Descending))
End Sub
Enum ArrowType
Ascending
Descending
End Enum
Function GetArrowBitmap(ByVal type As ArrowType) As Bitmap
Dim bmp As New Bitmap(8, 8)
Dim gfx As Graphics = Graphics.FromImage(bmp)
Dim lightPen As Pen = SystemPens.ControlLightLight
Dim shadowPen As Pen = SystemPens.ControlDark
gfx.FillRectangle(System.Drawing.Brushes.Magenta, 0, 0, 8, 8)
If type = ArrowType.Ascending Then
gfx.DrawLine(lightPen, 0, 7, 7, 7)
gfx.DrawLine(lightPen, 7, 7, 4, 0)
gfx.DrawLine(shadowPen, 3, 0, 0, 7)
Else
gfx.DrawLine(lightPen, 4, 7, 7, 0)
gfx.DrawLine(shadowPen, 3, 7, 0, 0)
gfx.DrawLine(shadowPen, 0, 0, 7, 0)
End If
gfx.Dispose()
Return bmp
End Function
End Class
'注意事項若原Listview已設置imagelist則SetHeaderImageList必須放在imagelist後面執行
否則會指向listview原imagelist上的圖示
2. 針對第一個方法我所作的修改更為精簡
方法同上直接原生API方式實現, 此方法必須在有manifest或EnableVisualStyles開啟的情況下支援
(備註: 1.XP以下的OS不支援, 2.不受Theme關閉的影響)
Public Sub ShowHeaderIcon(ByVal list As ListView, ByVal columnIndex As Integer, ByVal sortOrder As SortOrder)
If columnIndex < 0 OrElse columnIndex >= list.Columns.Count Then
Return
End If
Dim hHeader As IntPtr = SendMessage(list.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero)
Dim colHdr As ColumnHeader = list.Columns(columnIndex)
Dim hd As HDITEM = New HDITEM
hd.mask = HDI_FORMAT
Dim align As HorizontalAlignment = colHdr.TextAlign
If align = HorizontalAlignment.Left Then
hd.fmt = HDF_LEFT Or HDF_STRING
Else
If align = HorizontalAlignment.Center Then
hd.fmt = HDF_CENTER Or HDF_STRING
Else
hd.fmt = HDF_RIGHT Or HDF_STRING
End If
End If
If sortOrder = sortOrder.Ascending Then
hd.fmt = hd.fmt Or HDF_SORTUP
ElseIf sortOrder = sortOrder.Descending Then
hd.fmt = hd.fmt Or HDF_SORTDOWN
End If
SendMessage(hHeader, HDM_SETITEM, New IntPtr(columnIndex), hd)
End Sub
3. http://groups.google.com.tw/groups hl=zh-TW&lr=&ie=UTF-8&selm=1092127868.280097%40news.thyssen.com
透過Unicode文字指標方式實現, 實作的方式最為簡單容易.
Dim mSortDirection As String = "ASC"
Private SortColumn As Integer = 1
Protected Sub ListView1_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
'remove sort icon from old column.
If SortColumn <> -1 Then
ListView1.Columns.Item(SortColumn).Text = ListView1.Columns.Item(SortColumn).Text.TrimEnd(Chr(32), Chr(32), Chr(32), ChrW(&H25B2), ChrW(&H25BC))
End If
If e.Column <> SortColumn Then
SortColumn = e.Column
mSortDirection = "ASC"
'add down icon
ListView1.Columns.Item(SortColumn).Text &= " " & ChrW(&H25B2)
Else
If mSortDirection = "ASC" Then
mSortDirection = "DESC"
'do the sort
'add down icon
ListView1.Columns.Item(SortColumn).Text &= " " & ChrW(&H25BC)
Else
mSortDirection = "ASC"
'do the sort
'add up icon
ListView1.Columns.Item(SortColumn).Text &= " " & ChrW(&H25B2)
End If
End If
End Sub