我正在尝试为窗口创建和管理编写自己的样板代码/库。我想要实现的是,程序员能够使用lambda参数调用函数,然后将在窗口关闭时执行。 (就像JavaScript JQuery使程序员能够添加事件处理程序的方式。)我试图创建的结构类似于:
window
类的对象Window
,它包含有关特定窗口的信息。 SetWinEventHook(...)
为其窗口设置事件挂钩。window.close(lambda)
,它将一个lambda函数添加到窗口的关闭事件处理程序列表/ vector
。我现在已经在互联网上搜索了一段时间,但我找不到任何方法来执行最后一步。我可以为事件添加一个钩子,当然,但是这个钩子必须是静态的,或者必须是没有捕获的lambda,所以没有办法与window对象通信?我想这意味着这是一个愚蠢的想法,但有没有办法以一种体面的方式实现这一点?
答案 0 :(得分:1)
汉斯指出,使用地图获取每个窗口句柄的窗口效果很好。我有一个带有窗口处理程序和窗口的(静态)地图:
map<HWND, Window *> Window::handlerWindows;
窗口的处理程序可以通过静态getter获取:
Window *Window::getWindow(HWND handler) {
return handlerWindows[handler];
}
窗口过程使用此方法获取窗口句柄的窗口,以使其处理事件:
LRESULT CALLBACK windowProcedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
Window *window = Window::getWindow(hwnd);
switch (msg) {
case WM_CLOSE:
window->handle(msg);
...
要添加处理程序,lambda将与事件常量一起提供,例如:
window->bind(WM_CLOSE, [&run](){
run = false;
return true;
});
这会将处理程序添加到事件处理程序列表中:
map<DWORD, vector<function<bool()>>> eventHandlers;
和
void Window::bind(DWORD event, function<bool ()> handler) {
eventHandlers[event].push_back(handler);
}
然后用以下方式处理事件:
void Window::handle(DWORD event) {
vector<function<bool ()>> handlers = eventHandlers[event];
for_each(handlers.begin(), handlers.end(), [](function<bool ()> handler){
handler();
});
}
这很有效。