.net 自定义Listview列向右排序图像
我支持一个.Net 2.0 Windows应用程序,它有一个自定义的listview控件以允许更大的灵活性。直到明年,我才被允许把这个带到新版本的gramework上。我们正在从XP迁移到Windows 7,我们已经发现了一个问题,即如何将列排序图像(向上/向下箭头)绘制到listview。当前在XP中,图像绘制在列文本的右侧。然而,在Windows7中,我遇到了访问冲突异常。现在,我知道错误在于使用非托管代码对内存的不当处理,如下所示。我正在寻找一种方法,使用托管代码以安全的方式模拟下面的内容.net 自定义Listview列向右排序图像,.net,vb.net,.net,Vb.net,我支持一个.Net 2.0 Windows应用程序,它有一个自定义的listview控件以允许更大的灵活性。直到明年,我才被允许把这个带到新版本的gramework上。我们正在从XP迁移到Windows 7,我们已经发现了一个问题,即如何将列排序图像(向上/向下箭头)绘制到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
我能够使用以下方法从非托管代码迁移到托管代码:
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