tags:

views:

42

answers:

2

I'm creating a custom control class and since I want complete control of it, I register the class and want to use the class's

LRESULT CALLBACK OGLTOOLBAR::ToolProc(HWND, UINT, WPARAM, LPARAM)

but it's not letting me.

I'm doing:

HWND OGLTOOLBAR::create(HWND parent,HINSTANCE hInst, int *toolWidthPtr)
{
    if (toolhWnd != NULL)
    {
        return toolhWnd;
    }
    toolWidth = toolWidthPtr;

    ZeroMemory(&rwc,sizeof(rwc));
    rwc.lpszClassName = TEXT("OGLTool");
    rwc.hbrBackground = GetSysColorBrush(COLOR_BTNSHADOW);
    rwc.lpfnWndProc   = (WNDPROC)ToolProc;
    rwc.hCursor       = LoadCursor(0, IDC_ARROW);

    RegisterClass(&rwc);
    toolhWnd = CreateWindowEx(NULL, rwc.lpszClassName,NULL,
        WS_CHILD | WS_VISIBLE,
        0, 0, *toolWidth, 900, parent, 0, NULL, 0);  


    return toolhWnd;

}

what is the correct way of doing this?

Thanks

compiler says: Error 1 error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'WNDPROC'

A: 

Is ToolProc a static member? You can't pass member function pointers or functors as function pointers. C APIs only work in function pointers.

There's usually a way to tie "client data" to an object so that it is passed to the callback when triggered. You can use that information to carry instance specific data so that a static or global function can call the member variable in the correct class.

Noah Roberts
Actually, you would use GetWindowLongPtr/SetWindowLongPtr to hold the pointer to your instance object. No need to store that in some kind of external map. Index is set to DWLP_USER.
jmucchiello
A: 

If ToolProc isn't a static member, you can't pass a member function pointer as a callback like that, assuming you want ToolProc to be a non-static function, you can create a static member function, and use the GetWindowLong/SetWindowLong and the GWL_USERDATA area, to store a pointer to the current object(this), and have a static callback call the individual objects callback function, that can utilize the individual objects data members.

Assuming that ToolProc is not a static member of your OGLTOOLBAR class, you have to tie the this pointer of the object to the window handle, you can do this like so:

void OGLTOOLBAR::SetObjectToHWnd( HWND hWnd, LPARAM lParam )
{
    LPCREATESTRUCT cs = reinterpret_cast<LPCREATESTRUCT>(lParam);
    OGLTOOLBAR *pWnd = reinterpret_cast<OGLTOOLBAR*>(cs->lpCreateParams);

    SetLastError( 0 );

    if( !SetWindowLong( hWnd, GWL_USERDATA, reinterpret_cast<long>(pWnd) )
        && GetLastError() )
        //Do something about the error
}

OGLTOOLBAR *OGLTOOLBAR::GetObjectFromHWnd( HWND hWnd )
{
    return reinterpret_cast<OGLTOOLBAR*>(GetWindowLong(hWnd,GWL_USERDATA));
}

And then you have a static WndProc(Or ToolProc) member function like this:

LRESULT OGLTOOLBAR::StaticToolProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    if( uMsg == WM_NCCREATE )
        SetObjectToHwnd( hWnd, lParam );

    Window *pWnd = GetObjectFromWnd( hWnd );

    if( pWnd )
        return pWnd->ToolProc( hWnd, uMsg, wParam, lParam );
    else
        return DefWindowProc( hWnd, uMsg, wParam, lParam );
}

And then when you call the CreateWindow function in OGLTOOLBAR::create, pass reinterpret_cast<void*>(this) as the lpParam argument(The last one).

And each OGLTOOLBAR object will then have it's own ToolProc called for each instance, through the StaticToolProc function. Or at least I believe this should work.

Jacob