ListView CustomDraw не работает на 64-битных платформах - PullRequest
0 голосов
/ 19 января 2010

Я не уверен, что кто-то может помочь с этим, но я унаследовал этот код, и я понятия не имею, в чем проблема, и я не знаком с методом WndProc. Область, которая не запущена, - это раздел «Проверка пользовательских сообщений отрисовки». Мне нужно, чтобы запустить метод ProcessListCustomDraw (m), поэтому генерируются некоторые миниатюры. Я считаю, что оригинальное приложение было написано для .Net 1.1, поэтому я могу быть SOL. Любые идеи или мысли будут с благодарностью.

<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 background 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

Обновление: вот класс Win32:

' 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

1 Ответ

3 голосов
/ 19 января 2010

Если он работает на x86, то ваши объявления P / Invoke, вероятно, неверны. Использование Integer, где требуется IntPtr, что-то в этом роде. Вы не опубликовали их, я не могу сказать. Посетите pinvoke.net, чтобы получить нужные.


После просмотра ваших изменений: да, ваша декларация NMHDR неверна. Это должно выглядеть так:

<StructLayout(LayoutKind.Sequential)> _
Public Structure NMHDR
    Public hwndFrom As IntPtr
    Public idFrom As IntPtr              ' NOT INTEGER!!!
    Public code As Integer
End Structure
...