A static function like WindowProc(HWND, MSG, WPARAM, LPARAM) is suitable for processing the messages that are remitted to a window or control.
In my opinion, to associate an existing ATL C++ object with this messaging, it was decided to create intermediate short functions (having the same signature) at run-time, which receive the calls from Windows, and then redirect these calls to ATL functions, adding the missing ATL object. These things are called “thunks”.
For unknown reasons, it was chosen to pass the ATL objects via the HWND parameter. (The duplicate value of HWND is available in the m_hWnd member of the object, therefore it is not lost). See the ‘struct _stdcallthunk’ in ATL files for specific instructions generated for different microprocessors. One of the document (https://learn.microsoft.com/en-us/windows/win32/api/atlthunk/nf-atlthunk-atlthunk_initdata) mentions that “An ATL thunk has a signature of WNDPROC”.
Therefore, the Windows calls the thunk, which then call the ATL function, replacing the first parameter with an object. Then the target function reinterprets the first parameter as an object.