来自 win32 事件挂钩的 c++ 回调
c++ callback from win32 event hook
我正在尝试为 window 创建和管理编写自己的样板文件 code/library-stuff。我想要实现的是,程序员能够调用带有 lambda 参数的函数,然后该函数将在 window 关闭时执行。 (就像 JavaScript JQuery 使程序员能够添加事件处理程序的方式一样。)我试图创建的结构类似于:
- 我有一个自定义
Window
class 的对象 window
,它包含有关特定 window 的信息。
- 此对象为其 window 设置事件挂钩
SetWinEventHook(...)
。
- 程序员调用
window.close(lambda)
,它向 window 的关闭事件处理程序列表/vector
. 添加了一个 lambda 函数
- 发生关闭事件时,此挂钩会调用 window 的关闭事件列表中的回调。
我已经在互联网上搜索了一段时间,但我找不到执行最后一步的任何方法。当然,我可以向事件添加一个挂钩,但是这个挂钩必须是静态的,或者必须是没有捕获的 lambda,所以没有办法与 window 对象通信?我想这意味着这是一个愚蠢的想法,但有没有办法仍然以一种体面的方式实施它?
正如 Hans 指出的那样,使用地图为每个 window 句柄获取 window 效果很好。我有一个带有 window 处理程序和 windows:
的(静态)地图
map<HWND, Window *> Window::handlerWindows;
可以通过静态 getter 获取 window 的处理程序:
Window *Window::getWindow(HWND handler) {
return handlerWindows[handler];
}
window 过程使用此方法为 window 句柄获取 window,使其处理事件:
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();
});
}
这个效果很好。
我正在尝试为 window 创建和管理编写自己的样板文件 code/library-stuff。我想要实现的是,程序员能够调用带有 lambda 参数的函数,然后该函数将在 window 关闭时执行。 (就像 JavaScript JQuery 使程序员能够添加事件处理程序的方式一样。)我试图创建的结构类似于:
- 我有一个自定义
Window
class 的对象window
,它包含有关特定 window 的信息。 - 此对象为其 window 设置事件挂钩
SetWinEventHook(...)
。 - 程序员调用
window.close(lambda)
,它向 window 的关闭事件处理程序列表/vector
. 添加了一个 lambda 函数
- 发生关闭事件时,此挂钩会调用 window 的关闭事件列表中的回调。
我已经在互联网上搜索了一段时间,但我找不到执行最后一步的任何方法。当然,我可以向事件添加一个挂钩,但是这个挂钩必须是静态的,或者必须是没有捕获的 lambda,所以没有办法与 window 对象通信?我想这意味着这是一个愚蠢的想法,但有没有办法仍然以一种体面的方式实施它?
正如 Hans 指出的那样,使用地图为每个 window 句柄获取 window 效果很好。我有一个带有 window 处理程序和 windows:
的(静态)地图map<HWND, Window *> Window::handlerWindows;
可以通过静态 getter 获取 window 的处理程序:
Window *Window::getWindow(HWND handler) {
return handlerWindows[handler];
}
window 过程使用此方法为 window 句柄获取 window,使其处理事件:
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();
});
}
这个效果很好。