我正在考虑创建一个使用Win32 API和C++标准库的Window类库
我想添加处理窗口的信号/插槽功能消息。将boost :: bind对象转换为函数指针 - 实现消息映射
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 ::绑定,我得到了编译错误是这样的:
Window::addMsgHandler': cannot convert parameter 2 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(Window *,EventArgs *)'
,这意味着我必须要改变(?从简单的函数指针,以提高函数对象)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类派生的,我不知道该模板类型时,我定义类窗口。
有没有适当的方式来传递boost.bind对象作为函数参数?
我不想存储函数指针,但信号。 boost.function可以存储信号吗? –
恐怕我不明白你的意思,但是......然后,我应该将'msgMap'的类型从map更改为multimap,将函数添加到该multimap中,并且每次给出消息(WM_'s)时重新连接()所有的处理程序到相应的boost :: signal,并触发信号?这不奇怪吗?我认为应该为每个处理程序调用一次connect()。 –
我首先想到的情况是这样的:在地图中存储connect()'ed信号,而不是函数本身 –