From d8348065cbeb4c23f5594e4cabed7094a8e2e430 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 19 Mar 2013 20:50:49 +0000 Subject: - mir_unsubclassWindow introduced for the explicit window unsubclassing; - fix for subclassing in SRMM event handlers git-svn-id: http://svn.miranda-ng.org/main/trunk@4117 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/mir_core/subclass.cpp | 108 +++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 45 deletions(-) (limited to 'src/mir_core/subclass.cpp') diff --git a/src/mir_core/subclass.cpp b/src/mir_core/subclass.cpp index 183556402d..a2e7530f0e 100644 --- a/src/mir_core/subclass.cpp +++ b/src/mir_core/subclass.cpp @@ -96,8 +96,37 @@ MIR_CORE_DLL(void) mir_subclassWindowFull(HWND hWnd, WNDPROC wndProc, WNDPROC ol ///////////////////////////////////////////////////////////////////////////////////////// -MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd) +static void removeHook(MSubclassData *p, int idx) { + WNDPROC saveProc = p->m_hooks[idx]; + + // untie hook from a window to prevent calling mir_callNextSubclass from saveProc + for (int i=idx+1; i < p->m_iHooks; i++) + p->m_hooks[i-1] = p->m_hooks[i]; + p->m_iHooks--; + + // emulate window destruction + saveProc(p->m_hWnd, WM_DESTROY, 0, 0); + saveProc(p->m_hWnd, WM_NCDESTROY, 0, 0); +} + +MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd, WNDPROC wndProc) +{ + MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd); + if (p == NULL) + return; + + for (int i=0; i < p->m_iHooks; i++) { + if (p->m_hooks[i] == wndProc) { + removeHook(p, i); + i--; + } + } + + if (p->m_iHooks == 0) { + arSubclass.remove(p); + delete p; + } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -105,60 +134,49 @@ MIR_CORE_DLL(void) mir_unsubclassWindow(HWND hWnd) MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam) { MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd); - if (p) { - for (int i=p->m_iHooks-1; i >= 0; i--) { - if (p->m_hooks[i] == wndProc) { - // next hook exitst, call it - if (i != 0) - return p->m_hooks[i-1](hWnd, uMsg, wParam, lParam); - - // last hook called, ping the default window procedure - if (uMsg == WM_DESTROY) { - WNDPROC saveProc = p->m_origWndProc; - arSubclass.remove(p); - delete p; - - SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)saveProc); - LONG res = 0; - __try { - res = saveProc(hWnd, uMsg, wParam, lParam); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - } - return res; - } - - return p->m_origWndProc(hWnd, uMsg, wParam, lParam); - } - } - - // invalid / closed hook - return 0; + if (p == NULL) + return DefWindowProc(hWnd, uMsg, wParam, lParam); + + for (int i=p->m_iHooks-1; i >= 0; i--) { + if (p->m_hooks[i] != wndProc) + continue; + + // next hook exists, call it + if (i != 0) + return p->m_hooks[i-1](hWnd, uMsg, wParam, lParam); + + // last hook called, ping the default window procedure + if (uMsg != WM_DESTROY) + return p->m_origWndProc(hWnd, uMsg, wParam, lParam); + + WNDPROC saveProc = p->m_origWndProc; + arSubclass.remove(p); + delete p; + + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)saveProc); + return saveProc(hWnd, uMsg, wParam, lParam); } - return DefWindowProc(hWnd, uMsg, wParam, lParam); + + // invalid / closed hook + return 0; } ///////////////////////////////////////////////////////////////////////////////////////// MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst) { - for (int i=0; i < arSubclass.getCount(); i++) { + for (int i=arSubclass.getCount()-1; i >= 0; i--) { MSubclassData *p = arSubclass[i]; - for (int j=0; j < p->m_iHooks; ) { + for (int j=0; j < p->m_iHooks; j++) { if ( GetInstByAddress(p->m_hooks[j]) == hInst) { - WNDPROC saveProc = p->m_hooks[j]; - - // untie hook from a window to prevent calling mir_callNextSubclass from saveProc - for (int k=j+1; k < p->m_iHooks; k++) - p->m_hooks[k-1] = p->m_hooks[k]; - p->m_iHooks--; - - // emulate window destruction - saveProc(p->m_hWnd, WM_DESTROY, 0, 0); - saveProc(p->m_hWnd, WM_NCDESTROY, 0, 0); + removeHook(p, j); + j--; } - else j++; + } + + if (p->m_iHooks == 0) { + arSubclass.remove(p); + delete p; } } } -- cgit v1.2.3