代码之家  ›  专栏  ›  技术社区  ›  websch01ar

自定义Listview列向右排序图像

  •  0
  • websch01ar  · 技术社区  · 16 年前

    我支持一个.NET2.0Windows应用程序,它有一个自定义的listview控件,以允许更大的灵活性。直到明年我才被允许把这个带到新版本的gramework中。我们正在从XP迁移到windows7,并且我们发现了一个问题,即如何将列排序图像(向上/向下箭头)绘制到listview。当前在XP中,图像绘制在列文本的右侧。但是,在Windows7中,我遇到了访问冲突异常。现在,我知道错误是由于使用如下所示的非托管代码对内存进行了不正确的处理。我正在寻找一种方法,以模仿我们下面的安全方式使用托管代码。

    Public Shared Sub ColumnImageToRight(ByVal view As ListView, ByVal index As Integer)
            Dim LVM_GETCOLUMNW As Integer = &H1000 + 95
            Dim LVM_SETCOLUMNW As Integer = &H1000 + 96
            If Not view.IsHandleCreated Then
                Throw New InvalidOperationException("ListView not yet created, wait...")
            End If
            If index >= view.Columns.Count Then
                Throw New ArgumentOutOfRangeException("Column index out of range")
            End If
            Dim buf As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(GetType(LVCOLUMN)))
            Dim lvc As New LVCOLUMN()
            lvc.mask = &HFFFF
            Marshal.StructureToPtr(lvc, buf, False)
            Dim retval As IntPtr = SendMessageW(view.Handle, LVM_GETCOLUMNW, CType(index, IntPtr), buf)
            lvc = CType(Marshal.PtrToStructure(buf, GetType(LVCOLUMN)), LVCOLUMN)
            lvc.fmt = lvc.fmt Or &H1000
            Marshal.StructureToPtr(lvc, buf, False)
            retval = SendMessageW(view.Handle, LVM_SETCOLUMNW, CType(index, IntPtr), buf)
            Marshal.FreeHGlobal(lvc.pszText)
            Marshal.FreeHGlobal(buf)
        End Sub
    
    1 回复  |  直到 16 年前
        1
  •  1
  •   websch01ar    16 年前

    我能够使用以下方法从非托管代码迁移到托管代码:

    Private Sub ListViewEx_DrawColumnHeader(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawListViewColumnHeaderEventArgs) Handles Me.DrawColumnHeader
        Dim lcIcon As Drawing.Image = Nothing
        If miSelectedColumn = e.ColumnIndex Then
            Select Case Me.Sorting
                Case SortOrder.Ascending
                    lcIcon = Me.SmallImageList.Images(EnumSortImageKeys.Ascending)
                Case SortOrder.Descending
                    lcIcon = Me.SmallImageList.Images(EnumSortImageKeys.Descending)
                Case SortOrder.None
                    'Don't Do Anything
            End Select
        End If
        If lcIcon IsNot Nothing Then
            Dim liMargin As Integer = 4
            Dim x, y As Integer
            e.DrawBackground()
    
            Dim lcFontSize As Drawing.SizeF = e.Graphics.MeasureString(e.Header.Text, e.Font)
            x = CInt(lcFontSize.Width + e.Bounds.Left + (liMargin * 2))
            y = CInt((e.Bounds.Height / 2) - (lcIcon.Height / 2))
    
            Dim lsText As String = e.Header.Text
            If lcFontSize.Width + lcIcon.Width + liMargin > e.Bounds.Width Then
                Dim liCharWidth As Integer = CInt(lcFontSize.Width / lsText.Length)
                Dim liLength As Integer = CInt((e.Bounds.Width - (liMargin + lcIcon.Width)) / liCharWidth)
    
                lsText = lsText.Substring(0, liLength)
    
                lcFontSize = e.Graphics.MeasureString(lsText, e.Font)
                x = CInt(lcFontSize.Width + e.Bounds.Left + liMargin)
                y = CInt((e.Bounds.Height / 2) - (lcIcon.Height / 2))
                liMargin = CInt(liMargin / 2)
            End If
    
            e.Graphics.DrawString(lsText, e.Font, Drawing.Brushes.Black, e.Bounds.Left + liMargin, CSng((e.Bounds.Height / 2) - (lcFontSize.Height / 2)))
            e.Graphics.DrawImageUnscaled(lcIcon, x, y)
        Else
            e.DrawDefault = True
        End If
    End Sub
    
    Private Sub lv_DrawItem(ByVal view As Object, ByVal e As System.Windows.Forms.DrawListViewItemEventArgs) Handles Me.DrawItem
        e.DrawDefault = True
    End Sub
    
    推荐文章