ListView CustomDraw not working on 64 bit Platforms
I am not sure if anyone can help with this, but I inhertied this code and I have no idea what the issue is nor am I familiar with the WndProc method. The area that is not running is the "' check for custom draw message" section. I need it to run the ProcessListCustomDraw(m) method so some thumbnails are generated. I beleive the origianl application was wirtten for .Net 1.1, so I may be SOL. Any ideas or thoughts would be greatly appreciated.
<SecurityPermission(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.UnmanagedCode)> _
Protected Overrides Sub WndProc(ByRef m As Message)
Try
If m.Msg = Win32.Consts.WM_NCPAINT Then
' always repaint background if get wm_ncpaint
_backgroundDirty = True
End If
If m.Msg = Win32.Consts.WM_ERASEBKGND Then
' see if should repaint the background or not
If ProcessBackground() = False Then Return
End If
' look for messages to owner draw the listview items
If m.Msg = Win32.Consts.OCM_NOTIFY Then
' get the notification info
Dim notifyHeader As Win32.NMHDR = _
CType(m.GetLParam(GetType(Win32.NMHDR)), Win32.NMHDR)
' turn off backgroun开发者_开发问答d painting when get the item changed message
If notifyHeader.code = Win32.Consts.LVN_ITEMCHANGED Then
_paintBackground = False
End If
' check for custom draw message
If notifyHeader.hwndFrom.Equals(Me.Handle) And _
notifyHeader.code = Win32.Consts.NM_CUSTOMDRAW Then
_paintBackground = True
' process the message, returns true if performed custom
' drawing, otherwise false
If ProcessListCustomDraw(m) Then
Return
End If
End If
End If
MyBase.WndProc(m)
Catch ex As Exception
Log.WriteLog(Log.SZ_LOG_EXCEPTION & MethodBase.GetCurrentMethod().Name & " " & ex.Message)
End Try
End Sub
' one step closer to detecting if a listview item should be drawn
' return true if the listview item was drawn
Private Function ProcessListCustomDraw(ByRef m As Message) As Boolean
Try
' return true if performed custom drawing
Dim drawSelf As Boolean = False
' get custom draw information
Dim customDraw As Win32.NMCUSTOMDRAW = _
CType(m.GetLParam(GetType(Win32.NMCUSTOMDRAW)), Win32.NMCUSTOMDRAW)
' return different values in the message depending on the draw stage
Select Case customDraw.dwDrawStage
Case Win32.Consts.CDDS_PREPAINT
m.Result = New System.IntPtr(Win32.Consts.CDRF_NOTIFYITEMDRAW)
Case Win32.Consts.CDDS_ITEMPREPAINT
m.Result = New System.IntPtr(Win32.Consts.CDRF_SKIPDEFAULT)
If IsItemVisible(customDraw.dwItemSpec) Then
' finally, draw the listview item
Dim g As Graphics = Graphics.FromHdc(customDraw.hdc)
Try
DrawItemEg(g, CInt(customDraw.dwItemSpec))
drawSelf = True
Finally
g.Dispose()
End Try
Else
drawSelf = True
End If
Case Else
m.Result = New System.IntPtr(Win32.Consts.CDRF_DODEFAULT)
End Select
Return drawSelf
Catch ex As Exception
Log.WriteLog(Log.SZ_LOG_EXCEPTION & MethodBase.GetCurrentMethod().Name & " " & ex.Message)
End Try
End Function
Update: Here is the Win32 Class:
' win32 values
Private Class Win32
Public Enum Consts
' messages
WM_NCPAINT = &H85
WM_ERASEBKGND = &H14
WM_NOTIFY = &H4E
OCM_BASE = &H2000
OCM_NOTIFY = OCM_BASE + WM_NOTIFY
NM_CUSTOMDRAW = -12
NM_SETFOCUS = -7
LVN_ITEMCHANGED = -101
' custom draw return flags
CDRF_DODEFAULT = &H0
CDRF_SKIPDEFAULT = &H4
CDRF_NOTIFYITEMDRAW = &H20
' custom draw state flags
CDDS_PREPAINT = &H1
CDDS_ITEM = &H10000
CDDS_ITEMPREPAINT = CDDS_ITEM Or CDDS_PREPAINT
End Enum
<StructLayout(LayoutKind.Sequential)> _
Public Structure NMHDR
Public hwndFrom As IntPtr
Public idFrom As Integer
Public code As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
End Structure
<StructLayout(LayoutKind.Sequential)> _
Public Structure NMCUSTOMDRAW
Public hdr As NMHDR
Public dwDrawStage As Integer
Public hdc As IntPtr
Public rc As RECT
Public dwItemSpec As Integer
Public uItemState As Integer
Public lItemlParam As IntPtr
End Structure
End Class
If it works on x86 then your P/Invoke declarations are probably wrong. Using Integer where IntPtr is required, something like that. You didn't post them, I can't tell. Visit pinvoke.net to get the right ones.
After seeing your edit: yes, your NMHDR declaration is wrong. It must look like this:
<StructLayout(LayoutKind.Sequential)> _
Public Structure NMHDR
Public hwndFrom As IntPtr
Public idFrom As IntPtr ' NOT INTEGER!!!
Public code As Integer
End Structure
精彩评论