开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜