【问题标题】:Using a class callback for a custom control?为自定义控件使用类回调?
【发布时间】:2011-02-20 11:33:36
【问题描述】:

我正在创建一个自定义控件类,因为我想要完全控制它,所以我注册了该类并希望使用该类的

LRESULT 回调 OGLTOOLBAR::ToolProc(HWND, UINT, WPARAM, LPARAM)

但它不让我。

我在做:

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;

}

这样做的正确方法是什么?

谢谢

编译器说: 错误 1 ​​错误 C2440: 'type cast' : 无法从 'overloaded-function' 转换为 'WNDPROC'

【问题讨论】:

    标签: c++ c winapi


    【解决方案1】:

    如果 ToolProc 不是静态成员,则不能将成员函数指针作为回调传递,假设您希望 ToolProc 成为非静态函数,则可以创建静态成员函数,并使用GetWindowLong/SetWindowLong 和 GWL_USERDATA 区域,用于存储指向当前对象(this)的指针,并有一个静态回调调用各个对象的回调函数,可以利用各个对象的数据成员。

    假设 ToolProc 不是您的 OGLTOOLBAR 类的静态成员,您必须将对象的 this 指针绑定到窗口句柄,您可以这样做:

    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));
    }
    

    然后你有一个像这样的静态 WndProc(或 ToolProc) 成员函数:

    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 );
    }
    

    然后当您在OGLTOOLBAR::create 中调用CreateWindow 函数时,将reinterpret_cast&lt;void*&gt;(this) 作为lpParam 参数(最后一个)传递。

    然后每个 OGLTOOLBAR 对象将通过 StaticToolProc 函数为每个实例调用它自己的 ToolProc。或者至少我相信这应该可行。

    【讨论】:

    • 你不知道这篇文章对我有多大用处。
    【解决方案2】:

    ToolProc 是静态成员吗​​?您不能将成员函数指针或仿函数作为函数指针传递。 C API 仅适用于函数指针。

    通常有一种方法可以将“客户端数据”绑定到对象,以便在触发时将其传递给回调。您可以使用该信息来携带特定于实例的数据,以便静态或全局函数可以调用正确类中的成员变量。

    【讨论】:

    • 实际上,您可以使用 GetWindowLongPtr/SetWindowLongPtr 来保存指向您的实例对象的指针。无需将其存储在某种外部地图中。索引设置为 DWLP_USER。
    猜你喜欢
    • 1970-01-01
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    相关资源
    最近更新 更多