ListView中的中心子项图标

时间:2009-08-24 13:27:03

标签: vb.net winapi custom-controls

我想将图标放在我的一个列中。我当前添加图标的方式是在创建行之后调用AddIconToSubitem方法。如何修改我的自定义控件以使图标居中?

由于

Public Class ListViewSubIcons : Inherits System.Windows.Forms.ListView

    Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal Msg As Int32, ByVal wParam As Int32, ByRef lParam As LV_ITEM) As Boolean

    Public Structure LV_ITEM
        Public mask As UInt32
        Public iItem As Int32
        Public iSubItem As Int32
        Public state As UInt32
        Public stateMask As UInt32
        Public pszText As String
        Public cchTextMax As Int32
        Public iImage As Int32
        Public lParam As IntPtr
    End Structure

    Private Structure NMHDR
        Public hwndFrom As IntPtr
        Public idFrom As Integer
        Public code As Integer
    End Structure

    ' listview
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
    Private Structure LVHITTESTINFO
        Public pt As Point
        Public flags As Integer
        Public iItem As Integer
        Public iSubItem As Integer
    End Structure

    Public Const LVM_FIRST As Int32 = &H1000
    Public Const LVM_GETITEM As Int32 = LVM_FIRST + 5
    Public Const LVM_SETITEM As Int32 = LVM_FIRST + 6
    Public Const LVIF_TEXT As Int32 = &H1
    Public Const LVIF_IMAGE As Int32 = &H2

    Public Const LVW_FIRST As Integer = &H1000
    Public Const LVM_GETEXTENDEDLISTVIEWSTYLE As Integer = LVW_FIRST + 54

    Public Const LVS_EX_GRIDLINES As Integer = &H1
    Public Const LVS_EX_SUBITEMIMAGES As Integer = &H2
    Public Const LVS_EX_CHECKBOXES As Integer = &H4
    Public Const LVS_EX_TRACKSELECT As Integer = &H8
    Public Const LVS_EX_FULLROWSELECT As Integer = &H20 ' applies to report mode only

    Private Const WM_NOTIFY As Integer = &H4E

    ' Change the style to accept images on subitems.
    Public Sub New()

        ' This call is required by the Windows.Forms Form Designer.
        InitializeComponent()

        AddHandler Me.HandleCreated, AddressOf ListViewWithIcons_HandleCreated

    End Sub

    Private Sub ListViewWithIcons_HandleCreated(ByVal sender As Object, ByVal e As EventArgs)
        ' Change the style of listview to accept image on subitems
        Dim m As System.Windows.Forms.Message = New Message
        m.HWnd = Me.Handle
        m.Msg = LVM_GETEXTENDEDLISTVIEWSTYLE
        m.LParam = New IntPtr(LVS_EX_GRIDLINES Or LVS_EX_FULLROWSELECT Or LVS_EX_SUBITEMIMAGES Or LVS_EX_CHECKBOXES Or LVS_EX_TRACKSELECT)
        m.WParam = IntPtr.Zero
        Me.WndProc(m)
    End Sub

    ' Add an icon to a subitem.
    Public Sub AddIconToSubitem(ByVal row As Integer, ByVal col As Integer, ByVal icon_num As Integer)
        Dim lvi As New LV_ITEM()
        lvi.iItem = row
        lvi.iSubItem = col

        ' Indicate what we're setting.
        lvi.mask = LVIF_IMAGE
        lvi.iImage = icon_num   ' Image index in the ImageList.

        ' Send the LVM_SETITEM message.
        SendMessage(Me.Handle, LVM_SETITEM, 0, lvi)
    End Sub

End Class

1 个答案:

答案 0 :(得分:1)

我将在这里回答我自己的问题:)

Public Class ListViewSubIcons : Inherits System.Windows.Forms.ListView

    Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    Public Const LVW_FIRST As Integer = &H1000
    Public Const LVM_GETEXTENDEDLISTVIEWSTYLE As Integer = LVW_FIRST + 54

    Public Const LVS_EX_GRIDLINES As Integer = &H1
    Public Const LVS_EX_SUBITEMIMAGES As Integer = &H2
    Public Const LVS_EX_CHECKBOXES As Integer = &H4
    Public Const LVS_EX_TRACKSELECT As Integer = &H8
    Public Const LVS_EX_FULLROWSELECT As Integer = &H20 ' applies to report mode only

    Private Const WM_NOTIFY As Integer = &H4E

    Public Enum ListStatus
        OK
        Fail
        Upgrade
    End Enum

    Private _liststatus As ListStatus = ListStatus.OK
    Public WriteOnly Property SetListStatus() As ListStatus
        Set(ByVal value As ListStatus)
            _liststatus = value
        End Set
    End Property


    ' Change the style to accept images on subitems.
    Public Sub New()

        ' This call is required by the Windows.Forms Form Designer.
        InitializeComponent()

        AddHandler Me.HandleCreated, AddressOf ListViewWithIcons_HandleCreated
        AddHandler Me.DrawSubItem, AddressOf lvResult_DrawSubItem
        AddHandler Me.DrawColumnHeader, AddressOf lvResult_DrawColumnHeader

        Me.OwnerDraw = True

    End Sub

    Private Sub ListViewWithIcons_HandleCreated(ByVal sender As Object, ByVal e As EventArgs)
        ' Change the style of listview to accept image on subitems
        Dim m As System.Windows.Forms.Message = New Message
        m.HWnd = Me.Handle
        m.Msg = LVM_GETEXTENDEDLISTVIEWSTYLE
        m.LParam = New IntPtr(LVS_EX_GRIDLINES Or LVS_EX_FULLROWSELECT Or LVS_EX_SUBITEMIMAGES Or LVS_EX_CHECKBOXES Or LVS_EX_TRACKSELECT)
        m.WParam = IntPtr.Zero
        Me.WndProc(m)
    End Sub

    ' Handle DrawSubItem event
    Private Sub lvResult_DrawSubItem(ByVal sender As Object, ByVal e As         DrawListViewSubItemEventArgs)

        'Only subitems with just icon's will have no text
        If e.SubItem.Text = "" Then
            Dim xpos = e.SubItem.Bounds.Location.X + (e.SubItem.Bounds.Width / 2) - 8
            Dim p As New PointF(xpos, e.SubItem.Bounds.Location.Y)
            e.DrawBackground()
            Select Case _liststatus
                Case ListStatus.OK
                    e.Graphics.DrawImage(My.Resources.Symbol_Check, p)
                Case ListStatus.Fail
                    e.Graphics.DrawImage(My.Resources.Delete, p)
                Case ListStatus.Upgrade
                    e.Graphics.DrawImage(My.Resources.Component1, p)
            End Select
        Else
            e.DrawDefault = True
        End If

    End Sub

    ' Handle DrawColumnHeader event
    Private Sub lvResult_DrawColumnHeader(ByVal sender As Object, ByVal e As DrawListViewColumnHeaderEventArgs)
        e.DrawDefault = True
        e.DrawBackground()
        e.DrawText()
    End Sub

End Class