来自win32事件钩子的c ++回调

时间:2016-11-12 12:38:52

标签: c++ lambda win32gui

我正在尝试为窗口创建和管理编写自己的样板代码/库。我想要实现的是,程序员能够使用lambda参数调用函数,然后将在窗口关闭时执行。 (就像JavaScript JQuery使程序员能够添加事件处理程序的方式。)我试图创建的结构类似于:

  • 我有一个自定义window类的对象Window,它包含有关特定窗口的信息。
  • 此对象使用SetWinEventHook(...)为其窗口设置事件挂钩。
  • 程序员调用window.close(lambda),它将一个lambda函数添加到窗口的关闭事件处理程序列表/ vector
  • 当发生关闭事件时,此挂钩会从窗口的关闭事件列表中调用回调。

我现在已经在互联网上搜索了一段时间,但我找不到任何方法来执行最后一步。我可以为事件添加一个钩子,当然,但是这个钩子必须是静态的,或者必须是没有捕获的lambda,所以没有办法与window对象通信?我想这意味着这是一个愚蠢的想法,但有没有办法以一种体面的方式实现这一点?

1 个答案:

答案 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();
    });
}

这很有效。