将boost :: bind对象转换为函数指针 - 实现消息映射

时间:2012-10-02 16:08:06

标签: c++ winapi boost signals

我正在考虑创建一个使用Win32 API和C ++标准库的Window类库 我想添加处理窗口消息的信号/插槽功能。

using namespace std;
using namespace boost::signals2;
typedef signal<void (Window*, EventArgs*)> WndEvent; 

class EventArgs { public: HWND hWnd; WPARAM wParam; LPARAM lParam; };

class Window {
    protected: unordered_map<UINT, WndMsg*> msgMap;
    public: void addMsgHandler(UINT msg, void (*handler)(Window*, EventArgs*)) {
        auto iter=msgMap.find(msg);
        if(iter==msgMap.end()) {
            WndEvent* newEvent = new WndEvent();
            newEvent->connect(handler);
            msgMap.insert(make_pair(msg, newEvent));
        }
        else iter->second->connect(handler);
    }

    private: LRESULT wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lparam) {
        for(auto iter=msgMap.begin(); iter!=msgMap.end(); iter++)
            iter->second->();
    }
};

使用该库时:

class Form : public Window {
    void initialize() {// add here pair of 'message' and 'corresponding handler'
        addMsgHandler(WM_LBUTTONUP, boost::bind(&Form::onLButtonUp, this, _1, _2));
        ...
    }
    void onLButtonUp(Window* sender, EventArgs* e) { // event handler
        wchar_t buf[1000]; 
        wsprintf(buf, L"(%d, %d) clicked", GET_X_LPARAM(e->lParam), GET_Y_LPARAM(e->lParam));
        MessageBox(0, buf, L"", MB_OK);
    }
}

这里的问题是onLButtonUp的签名不匹配,因为它是一个类成员函数。
所以我尝试使用boost :: bind,我得到了这样的编译错误:

 Window::addMsgHandler': cannot convert parameter 2 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(Window *,EventArgs *)'

这意味着我必须更改(从简单的函数指针到boost函数对象?)addMsgHandler()的签名但是

我无法确定要传递的数据类型(包含很长的模板参数)。

编译错误消息显示

R=void,            
F=boost::_mfi::mf2<void,Form,Window *,EventArgs *>,1>                           
L=boost::_bi::list3<boost::_bi::value<Form*>,boost::arg<1>,boost::arg<2>>                

此外,由于许多其他类将从类Window派生,我在定义类 Window 时无法知道模板类型。

是否有正确的方法将boost.bind对象作为函数参数传递?

1 个答案:

答案 0 :(得分:0)

像这样定义:

void addMsgHandler(UINT msg, const function<void(Window* , EventArgs*)>& slot);

或者甚至喜欢这样:

void addMsgHandler(UINT msg, const WndEvent::slot_type &slot);

现在,在调用此函数时,slot参数应该是“可调用的”,接受类型为Window *EventArgs *的2个参数,您可以使用{{1}创建这样的插槽}},mem_fnboost::bind,或只传递适当的原始函数ptr。