locked
'AddressOf' expression cannot be converted to 'Long' RRS feed

  • Question

  • I am getting this error with the following code ...

    " 'AddressOf' expression cannot be converted to 'Long' because 'Long' is not a delegate type. "

    I thought AddressOf returned a long value in vb6 but I found out it now returns a "delegate" type in VB10 ... I am new to VB 10 and can't seem to wrap my head around this new type. Can anyone help explain to me how I can to turn a "delegate" type to a long value to pass to the "user32" SetWindowLong funtion?

        Private Const GWL_WNDPROC = -4
        Private Const WM_GETMINMAXINFO = &H24

        Public lpPrevWndProc As Long
        Public gHW As Long

        Public Structure POINTAPI

            Dim x As Long
            Dim y As Long

        End Structure

        Public Structure MINMAXINFO

            Dim ptReserved As POINTAPI
            Dim ptMaxSize As POINTAPI
            Dim ptMaxPosition As POINTAPI
            Dim ptMinTrackSize As POINTAPI
            Dim ptMaxTrackSize As POINTAPI

        End Structure
     
        Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
        Private Declare Sub CopyMemoryToMinMaxInfo Lib "KERNEL32" Alias "RtlMoveMemory" (hpvDest As MINMAXINFO, ByVal hpvSource As Long, ByVal cbCopy As Long)
        Private Declare Sub CopyMemoryFromMinMaxInfo Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal hpvDest As Long, hpvSource As MINMAXINFO, ByVal cbCopy As Long)
        Private Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long


        Public Sub Hook()

            lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOf WindowProc)

        End Sub

        Public Sub Unhook()

            Dim temp As Long
            temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)

        End Sub

        Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

            Dim myScreens() As Screen = Screen.AllScreens
            Dim MinMax As MINMAXINFO
            If uMsg = WM_GETMINMAXINFO Then
                CopyMemoryToMinMaxInfo(MinMax, lParam, Len(MinMax))
                MinMax.ptMinTrackSize.x = 100
                MinMax.ptMinTrackSize.y = 100
                MinMax.ptMaxTrackSize.x = myScreens(0).Bounds.Height + 10
                MinMax.ptMaxTrackSize.y = myScreens(0).Bounds.Width + 10
                CopyMemoryFromMinMaxInfo(lParam, MinMax, Len(MinMax))
                WindowProc = DefWindowProc(hw, uMsg, wParam, lParam)
            Else
                WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
            End If

        End Function


    • Edited by rdaviddd Saturday, July 28, 2012 10:30 PM
    Saturday, July 28, 2012 10:15 PM

Answers

  • Hi,

    there's a forum about upgrading: http://social.msdn.microsoft.com/Forums/en-US/vbinterop/threads

    Maybe a moderator can move it.

    It would have helped if you had used the upgrade wizard so that at least some data types are matching. In general, if you want to translate, you should know both languages well before. Anyway, first step is changing Long to Integer. However, as VB6 didn't have a pointer type, Long was the replacment. In VB.Net, it is IntPtr now. So, wherever a pointer-size type is required, use IntPtr. Wherever a 32 bit size integer is required use Integer (or Int32).

    I won't correct all API declarations now. Have a look at pInvoke.net and copy from there.

    Regarding the question: SetWindowLong  has been superseded by SetWindowLongPtr. The last parameter is IntPtr now or a delegate:

    Private Delegate Function WndProcDelegate(ByVal hWnd As IntPtr, ByVal msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

    That means, keep two declarations of SetWindowLongPtr: One with IntPtr and one with WndProcDelegate as the last parameter's type.

    Then you also need to change:

       Public lpPrevWndProc As IntPtr
       Public gHW As IntPtr
    
       Public Sub Hook()
    
          lpPrevWndProc = SetWindowLongPtr(gHW, GWL_WNDPROC, AddressOf WindowProc)
    
       End Sub
    
       Public Sub Unhook()
    
          Dim temp As IntPtr
          temp = SetWindowLongPtr(gHW, GWL_WNDPROC, lpPrevWndProc)
    
       End Sub

     Function WindowProc(ByVal hw As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    '''' .....
    End Function

    Let me know if I forgot something.



    Armin


    Saturday, July 28, 2012 10:36 PM

All replies

  • Hi,

    there's a forum about upgrading: http://social.msdn.microsoft.com/Forums/en-US/vbinterop/threads

    Maybe a moderator can move it.

    It would have helped if you had used the upgrade wizard so that at least some data types are matching. In general, if you want to translate, you should know both languages well before. Anyway, first step is changing Long to Integer. However, as VB6 didn't have a pointer type, Long was the replacment. In VB.Net, it is IntPtr now. So, wherever a pointer-size type is required, use IntPtr. Wherever a 32 bit size integer is required use Integer (or Int32).

    I won't correct all API declarations now. Have a look at pInvoke.net and copy from there.

    Regarding the question: SetWindowLong  has been superseded by SetWindowLongPtr. The last parameter is IntPtr now or a delegate:

    Private Delegate Function WndProcDelegate(ByVal hWnd As IntPtr, ByVal msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

    That means, keep two declarations of SetWindowLongPtr: One with IntPtr and one with WndProcDelegate as the last parameter's type.

    Then you also need to change:

       Public lpPrevWndProc As IntPtr
       Public gHW As IntPtr
    
       Public Sub Hook()
    
          lpPrevWndProc = SetWindowLongPtr(gHW, GWL_WNDPROC, AddressOf WindowProc)
    
       End Sub
    
       Public Sub Unhook()
    
          Dim temp As IntPtr
          temp = SetWindowLongPtr(gHW, GWL_WNDPROC, lpPrevWndProc)
    
       End Sub

     Function WindowProc(ByVal hw As IntPtr, ByVal uMsg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    '''' .....
    End Function

    Let me know if I forgot something.



    Armin


    Saturday, July 28, 2012 10:36 PM
  • Iiin addition:

    • The Len() function is not appropriate for calculating the size of an unmanaged structure because it calculates the size of the object if written to a file. That's not necessarily equal. Call System.Runtime.InteropServices.Marshal.SizeOf instead. So the call would be:

          RtlMoveMemory(MinMax, lParam, New IntPtr(Marshal.SizeOf(MinMax)))

    • However, RtlMoveMemory can be replaced by Marshal.PtrToStructure resp. StructureToPtr:

         MinMax = DirectCast(Marshal.PtrToStructure(lParam, GetType(MINMAXINFO)), MINMAXINFO)
         '...
         Marshal.StructureToPtr(MinMax, lParam, False)


    Armin


    Saturday, July 28, 2012 11:02 PM