/* * AUTHOR * N. Nielsen * * VERSION * 2.2.0b * * LICENSE * This software is in the public domain. * * The software is provided "as is", without warranty of any kind, * express or implied, including but not limited to the warranties * of merchantability, fitness for a particular purpose, and * noninfringement. In no event shall the author(s) be liable for any * claim, damages, or other liability, whether in an action of * contract, tort, or otherwise, arising from, out of, or in connection * with the software or the use or other dealings in the software. * * SUPPORT * Send bug reports to: */ #ifndef __ATLWINHK_H__ #define __ATLWINHK_H__ ///////////////////////////////////////////////////////////////////////// // Hooks an CWindowImpl to windows that the API or other code creates // By Stef: 06/10/99 // Use this macro in the class definition and pass class name // as first param #define DECLARE_HOOK_AND_SUBCLASS(Class) \ HHOOK m_hHookCur; \ static LRESULT CALLBACK HookCreateProc(int nCode, \ WPARAM wParam, \ LPARAM lParam) \ { \ Class* pThis = (Class*) _Module.ExtractCreateWndData(); \ \ if (nCode != HCBT_CREATEWND) \ { \ /*Add it back again*/ \ _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis); \ /*wait for HCBT_CREATEWND just pass others on...*/ \ return CallNextHookEx(pThis->m_hHookCur, nCode, wParam, lParam); \ } \ \ pThis->SubclassWindow((HWND)wParam); \ \ UnhookWindowsHookEx(pThis->m_hHookCur); \ HHOOK hHookCur = pThis->m_hHookCur; \ pThis->m_hHookCur = NULL; \ \ return CallNextHookEx(hHookCur, nCode, wParam, lParam); \ } // Use this *immediately* before the code that creates the window // It will subclass the first window that's created by that thread // so add immediately before. #define HOOK_AND_SUBCLASS_NEXT() \ ((m_hHookCur = SetWindowsHookEx(WH_CBT, HookCreateProc, NULL, ::GetCurrentThreadId())) == NULL) const LPCTSTR kDialogClass = (LPCTSTR)0x00008002; template class CHookWindow { public: CHookWindow() { m_hHookCur = NULL; m_szHookClass = NULL; m_szHookName = NULL; } bool SubclassNext(LPCTSTR szClass = NULL, LPCTSTR szName = NULL) { _Class* pThis = (_Class*)this; _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis); m_hHookCur = SetWindowsHookEx(WH_CBT, HookCreateProc, NULL, ::GetCurrentThreadId()); if(m_hHookCur) { m_szHookClass = szClass; m_szHookName = szName; } return m_hHookCur == NULL; } static LRESULT CALLBACK HookCreateProc(int nCode, WPARAM wParam, LPARAM lParam) { _Class* pThis = (_Class*) _Module.ExtractCreateWndData(); HHOOK hHookCur = pThis->m_hHookCur; bool bSkip = false; if(nCode != HCBT_CREATEWND) { bSkip = true; } else { CBT_CREATEWND* pCreate = (CBT_CREATEWND*)lParam; if(pThis->m_szHookClass) { // If it's not a pointer (for at least two bytes) if(IsBadReadPtr(pCreate->lpcs->lpszClass, 2) || IsBadReadPtr(pThis->m_szHookClass, 2)) // Then just compare values bSkip = pCreate->lpcs->lpszClass != pThis->m_szHookClass; else // Otherwise compare strings bSkip = _tcsicmp(pCreate->lpcs->lpszClass, pThis->m_szHookClass) != 0; } if(pThis->m_szHookName) { if(IsBadReadPtr(pCreate->lpcs->lpszName, _tcslen(pThis->m_szHookName)) || _tcsicmp(pCreate->lpcs->lpszName, pThis->m_szHookName)) bSkip = true; } } if(bSkip) { /*Add it back again*/ _Module.AddCreateWndData(&(pThis->m_thunk.cd), pThis); } else { pThis->SubclassWindow((HWND)wParam); UnhookWindowsHookEx(pThis->m_hHookCur); pThis->m_hHookCur = NULL; } return CallNextHookEx(hHookCur, nCode, wParam, lParam); } protected: HHOOK m_hHookCur; LPCTSTR m_szHookName; LPCTSTR m_szHookClass; }; #endif //__ATLWINHK_H__