2016-11-12 96 views
0

我想寫我自己的樣板代碼/庫東西窗口創建和管理。我試圖實現的是,程序員可以使用lambda參數調用函數,然後在窗口關閉時執行它。 (喜歡的方式的JavaScript JQuery的程序員能夠添加事件處理程序)。我試圖創建的結構是這樣的:從win32事件掛鉤C++回調

  • 我有我的自定義Window類,其中包含有關特定窗口信息的對象window
  • 該對象爲其窗口設置了一個事件掛鉤,其編號爲SetWinEventHook(...)
  • 程序員調用window.close(lambda),它向窗口的關閉事件處理程序列表/ vector添加了一個lambda函數。
  • 當關閉事件發生時,該掛鉤從窗口的關閉事件列表中調用回調。

我一直在interwebs上尋找一段時間,但我找不到任何方法來執行最後一步。我可以爲事件添加一個鉤子,當然,但是這個鉤子必須是靜態的,或者必須是一個沒有捕獲的lambda,所以沒有辦法與窗口對象進行通信?我想這意味着這是一個愚蠢的想法,但是還有什麼方法可以以一種體面的方式來實現它嗎?

+1

僅調用一次SetWinEventHook()。回調提供了窗口句柄。所以你需要一個靜態'map '來找回你的Window對象。 –

+0

我可能並沒有完全清楚這一點,但我確實只調用一次SetWinEventHook。關於地圖,這確實是一個出色的想法!你能否從中做出完整的答案?然後,我可以將其標記爲「回答了我的問題」。 ;) –

+0

不知道如何使它「完整」。只要告訴我們你在自己的帖子中做了什麼,並將其標記爲解決問題的答案。 –

回答

1

正如漢斯指出的那樣,使用地圖獲取每個窗口句柄的窗口效果很好。我有一個(靜態)地圖窗口句柄和窗口:

map<HWND, Window *> Window::handlerWindows; 

窗口的句柄可以通過靜態吸氣來獲取:

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

這工作得很好。