Advertisement

passing class::WindowProc to lpfnWndProc

Started by March 25, 2000 08:21 PM
5 comments, last by drago 24 years, 7 months ago
I want to pass a class member method as the message processor. So at WNDCLASS.lpfnWndProc I type my method class::WindowProc. This doesn''t work because I get a type cast error: error C2440: ''type cast'' : cannot convert from '''' to ''long (__stdcall *)(struct HWND__ *,unsigned int,unsigned int,long)'' I know somebody posted the same question about a year ago, but I don''t remember the solution ---------- Drago
osu!
The problem is that whenever you have a class function, there''s a hidden paramter, the this pointer. In order to get around it you either need to make a static member function or a non-member function.

See the article: "Calling All Members: Member Functions as Callbacks" in the MSDN for more information.
Advertisement
The problem with static member functions is that it cannot use member variables and it cannot be virtual. (I''m not 100% sure of this)

The way Microsoft solves this is that they use a non-member function that calls the class'' WindowProc. To do this they have a global pointer to the class that is initialized in the class'' constructor. This is true for their DirectX samples at least.
I can confirm that static member functions cannot be declared virtual.

However, I do have to clarify Spellbound''s post. There is no single Microsoft official way to solve this. Again, they recommend no less than five different methods for using member functions as callback routines, as in the article mentioned in my previous post.
Actually, you can store 4 bytes of extra information in the window memory itself (which just happens to be the size of a pointer!). To do this (yes, it's legal ): 1) pass the pointer to the window object (usually 'this') to CreateWindow() or CreateWindowEx() as the extra parameter. 2) In your static WndProc(), catch the WM_CREATE message and extract that window object pointer from the lParam, which you do by casting it to a CREATESTRUCT* and then get it from the lpCreateParams member. If it's non-NULL, then you store it in the window's memory, with SetWindowLong(). 3) You call your window object's pointer if it's not NULL, or DefWindowProc().

Presto! Any messages after WM_CREATE have a pointer to the object, which was stored in the extra window memory. Then you can use that pointer until the window is destroyed.

Here's my static WndProc():



LRESULT CALLBACK Window:: Procedure(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
Window* pWindow = NULL;

if( nMsg == WM_CREATE )
{
// Extract the window pointer parameter.
CREATESTRUCT* pCS = (CREATESTRUCT*) lParam;
pWindow = (Window*) pCS->lpCreateParams;

if( pWindow )
{
// Save it in the window handle.
SetWindowLong(hWnd, GWL_USERDATA, (LONG) pWindow);

// Store the window handle in the object.
pWindow->m_hWnd = hWnd;
}
}
else
{
// Extract the object from the window handle.
pWindow = (Window*) GetWindowLong(hWnd, GWL_USERDATA);
}

if( pWindow )
{
// Set the object's message and parameters.
pWindow->m_nMsg = nMsg;
pWindow->m_wParam = wParam;
pWindow->m_lParam = lParam;

// Let the object handle it.
return pWindow->OnMessage();
}
else
{
// Just do the default if the window is not created yet.
return DefWindowProc(hWnd, nMsg, wParam, lParam);
}
}



Keep in mind that there are usually other messages before WM_CREATE, so you have to call DefWindowProc() if the pointer you extract is NULL. Also, I assigned the message parameters to data members, but you don't have to -- you can just pass them as parameters to OnMessage() or whatever you're using.

Good Luck!


- null_pointer


Edited by - null_pointer on 3/26/00 6:46:30 AM

Edited by - null_pointer on 3/26/00 6:48:59 AM
I would like to thank null_pointer for the above solution. I have already exchanged my old one for this, and it is great. Now I can keep all data within the window class and still make clean derivations of it.

Thank you!
Advertisement
Spellbound: Thanks! (Someone actually appreciates it... )

Good Luck!


- null_pointer

This topic is closed to new replies.

Advertisement