Archived

This topic is now archived and is closed to further replies.

MatrixCubed

WinProc inside a class?

Recommended Posts

I''m attempting to store a WinProc function inside a class, but the compiler just won''t accept it... the latest error is as follows:
error C2440: ''='' : cannot convert from 
''long (__stdcall CApplication::*)(void *,unsigned int,unsigned int,long)'' to 
''long (__stdcall *)(void *,unsigned int,unsigned int,long)''

There is no context in which this conversion is possible
 
Ideas? I''m not sure where to find a solution to this sort of thing, so your insight is appreciated. MatrixCubed

Share this post


Link to post
Share on other sites
The reason you can''t use a non-static member for a WinProc is because all non-static members have the hidden ''this'' pointer, which changes function prototype. The error message you''re getting is saying that you''re trying to use a pointer to a member function (__stdcall CApplication::*), when you need just a pointer to a function (__stdcall *). Remember, a member function (non-static) needs a ''this'' pointer in order to be called. This means you can''t just pass around member function pointers and call them, without having a specific object to call it against. One of the shortcomings of C++, imho.
One way around this is to make the function static, as richardve mentioned. But you probably want a specific object to recieve the message, so you need to track which object the static function should forward to. I recommend either a global (evil) if you need to maintain multiple instances of the class, or make the class a singleton if you only need one. You could go more exotic, though, and maintain an associative array that the static function would use to determain which instance to forward the message to.
Ok, long reply, but this is a problem I''ve seen a lot of people run into. Just remember, a pointer to a non-static member function is NOT the same as a pointer to an equivalent non-member function: the hidden ''this'' pointer changes the signature of the function.
If you''re interested in this, look into Borland''s __closure extension, which binds member function pointers to instances. Unforunately, it''s a proprietary feature, but an interesting solution nonetheless.

Morbo

Share this post


Link to post
Share on other sites
My solution was
    
//

// Internal (hidden) window procedure
static LRESULT CALLBACK InternalWindowProc(HWND p_hWnd, UINT p_uMessage,
WPARAM p_wParam, LPARAM p_lParam);
//

// ####################################################################### //

// # CMyApp::CreateEngineWindow() # //

// # Creates a suiting window for use by the application # //

// ####################################################################### //

HWND CMyApp::CreateEngineWindow(...) {
HWND l_hWnd;
WNDCLASSEX l_wcx;
...
l_wcx.lpfnWndProc = InternalWindowProc;
RegisterClassEx(&l_wcx);
...
l_hWnd = CreateWindowEx(...);
SetProp(m_hWnd, "CMyApp_Owner\0", (HANDLE)this);
//

return l_hWnd;
}
//

// ####################################################################### //

// # CMyApp::WindowProc() # //

// # ''Official'' callback function for the main window # //

// ####################################################################### //

LRESULT CALLBACK CMyApp::WindowProc(UINT p_uMessage, WPARAM p_wParam, LPARAM p_lParam) {
switch(p_uMessage) {
...
}
return DefWindowProc(m_hWnd, p_uMessage, p_wParam, p_lParam);
}
//

// ####################################################################### //

// # InternalWindowProc() # //

// # Internal callback function for the main window # //

// ####################################################################### //

static LRESULT CALLBACK InternalWindowProc(HWND p_hWnd, UINT p_uMessage,
WPARAM p_wParam, LPARAM p_lParam) {
CMyApp *l_pThis;

// Get the pointer to the class owning this Window and give the

// call on to the class''s WindowProc()
l_pThis = (CMyApp *)GetProp(p_hWnd, "CMyApp_Owner\0");
if(l_pThis)
return l_pThis->WindowProc(p_uMessage, p_wParam, p_lParam);

// This point should not be reached, all windows should have
// the CMyApp_Owner value set

return DefWindowProc(p_hWnd, p_uMessage, p_wParam, p_lParam);
}


Works great, I''ve got the WindowProc() inside my class and there''s almost no overhead plus it works with any kind of window even in an MFC CStatic or CBitmap for example.
You can take a look at the complete sourcecode at
www.LunaticSystems.de/truefx/truefx3_beta3.zip.

-Markus-

Share this post


Link to post
Share on other sites