I found this terror today in a legacy application.
Program A uses SetWindowLong to hook the message loop for a Windows Form:
Friend Function StartListening() As Boolean
SetWindowLong(m_MappedWndHandle, GWL_WNDPROC, AddressOf WindowProcedure)
Program A then shells program B. Program B sends a WM_COPYDATA message to program A. Program A intercept the message, reads the data, and then passes the message to the form:
Public Function WindowProcedure(ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If msg = WM_COPYDATA Then
WindowProcedure = CallWindowProc(objMapMemoryData.GetWindowProcedureAddress, hwnd, msg, wParam, lParam)
objMapMemoryData.ReadMessage raises an event that is handled by the Form:
Friend Function ReadMessage(ByVal lParam As Long) As Boolean
‘SNIP: Copy memory around
Private Sub objMapMemoryData_MapMemoryDataEvent()
‘SNIP: Process event here
One of the things that VB6 is very good at is late binding. Back in the days before .NET late binding or OLE Automation as it was also known was one of the only ways to do certain tasks such as create reports in Excel, run Word mail merges from databases, or print nicely formatted documents. However there were downsides too. Applications that late bound to DLLs and EXEs had no means to ensure that the target supported the call being made or even that the target was installed on the PC. This allowed difficult to debug problems to creep into your program.
So the best solution to late binding problems was to early bind to any DLLs that you wanted to use. This way you could ensure that the interface was correct and that the DLL was installed on the system. However this led to another problem: DLL Hell. When an updated DLL was installed your system had to keep track of each version of the DLL and make sure that the right program called the right version. If a DLL was relied upon by a lot of programs and was regularly updated then a new installation could mess up an old program.
So .NET included ‘xcopy’ installation – simply include the right version of each referenced DLL in the same directory as the application and late binding became something that only ‘bad’ programmers did. Early bound DLLs also need to be loaded by the system when your program initiates.
The thing is that late binding solves a certain class of problem, one that often occurs in legacy applications. When adding new features supported by a DLL or refactoring old features to use new DLLs early binding to the DLL can cause problems with your installation program/routine, especially where DLL Hell issues have been previously overcome or there are a large number of support DLLs required for the application.
So a simple approach to enhancing or refactoring an old application is to develop with the references early bound and then switch to late binding and copy the required DLLs into either the application directory or another suitable location.