Even though VB Migration Partner can convert VB6 code that uses window subclassing (with some manual fixes on your part), you’d better off using one of the helper classes that the CodeArchitects.VBLibrary provides you with, the VB6WindowSubclasser class. This class enables you to implement subclassing in a simple and safe way and, just as important, without calling unmanaged code. Consider the following VB6 example that uses window subclassing:
Const WM_MOVE = &H3
Const WM_SIZING = &H214
Const WM_ACTIVATEAPP = &H1C
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hWnd As Long, ByVal ndx As Long, ByVal newValue 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
Const GWL_WNDPROC = -4
Dim saveHWnd As Long
Dim oldProcAddr As Long
Sub StartSubclassing(ByVal hWnd As Long)
saveHWnd = hWnd
oldProcAddr = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WndProc)
End Sub
Sub StopSubclassing()
SetWindowLong saveHWnd, GWL_WNDPROC, oldProcAddr
End Sub
Function WndProc(ByVal hWnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
WndProc = CallWindowProc(oldProcAddr, hWnd, uMsg, wParam, lParam)
Select Case uMsg
End Select
End Function
The VB6WindowSubclasser’s constructor takes the handle of the window to be subclassed and a delegate to a method that handles incoming messages (WndProc in this case). You can stop subclassing by invoking the VB6WindowSubclasser.Dispose method. Thus, the following VB.NET code is equivalent to the previous VB6 code:
Dim subclasser As VB6WindowSubclasser
Sub StartSubclassing(ByVal hWnd As Long)
subclasser = New VB6WindowSubclasser(hWnd, AddressOf WndProc)
End Sub
Sub StopSubclassing()
subclasser.Dispose()
End Sub
The code inside the WndProc method is same as before, except that you invoke the original window procedure by calling the VB6WindowSubclasser.CallWindowProc method:
Function WndProc(ByVal hWnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
WndProc = subclasser.CallWindowProc(hWnd, uMsg, wParam, lParam)
Select Case uMsg
End Select
End Function
You can implement this technique by editing the migrated VB.NET code or, even better, you can by adding some pragmas to the original VB6 code:
Const WM_MOVE = &H3
Const WM_SIZING = &H214
Const WM_ACTIVATEAPP = &H1C
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
ByVal hWnd As Long, ByVal ndx As Long, ByVal newValue 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
' This is used with the SetWindowLong API function.
Const GWL_WNDPROC = -4
Dim saveHWnd As Long ' The handle of the subclassed window.
Dim oldProcAddr As Long ' The address of the original window procedure
Sub StartSubclassing(ByVal hWnd As Long)
saveHWnd = hWnd
oldProcAddr = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WndProc)
End Sub
Sub StopSubclassing()
SetWindowLong saveHWnd, GWL_WNDPROC, oldProcAddr
End Sub
Function WndProc(ByVal hWnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
WndProc = CallWindowProc(oldProcAddr, hWnd, uMsg, wParam, lParam)
Select Case uMsg
End Select
End Function