www.pudn.com > HexEditOcx.rar > LanguageListener.h
/* * Softerra Hex Editor (c) Softerra, LLC 2005 * * FILENAME: LanguageListener.h * SUBSYSTEM: Core * DESCRIPTION: Implementation of the CLanguageListener class. * It hooks changing language keyboard loyout */ #pragma once #include#include #define WM_INPUTLANGMAGICEVENT 874 #if _ATL_VER <= 0x0300 // if ATL version 3.0 or above then define CComCritSecLock class // which already defined in later ATL versions. template
class CComCritSecLock { public: CComCritSecLock(T& cs) : m_cs(cs) { m_cs.Lock(); } ~CComCritSecLock() { m_cs.Unlock(); } private: T& m_cs; }; #endif ////////////////////////////////////////////////////////////////////////// // CLangEventListener // // Helper class implementing listener of change inputlanguage events // Usefull when this control is used in Non-MFC dialogs class ATL_NO_VTABLE CLangEventListener { public: CLangEventListener() {} virtual ~CLangEventListener() { DeactivateListener(); } public: HRESULT ActivateListener() { CComCritSecLock lock(s_ilCritSec); // activate hook if not yet if (!s_hhookCallWndProc) { s_hhookCallWndProc = ::SetWindowsHookEx( WH_CALLWNDPROC, InputLangCallWndProc, NULL, ::GetCurrentThreadId() ); if (!s_hhookCallWndProc) return HRESULT_FROM_WIN32( ::GetLastError() ); } // insert object in instance list (or move it to the end) s_InstanceList.remove(this); s_InstanceList.push_back(this); return S_OK; } void DeactivateListener() { CComCritSecLock lock(s_ilCritSec); // remove object from instance list s_InstanceList.remove(this); // remove HOOK if no more instances if (s_InstanceList.empty()) { ::UnhookWindowsHookEx(s_hhookCallWndProc); s_hhookCallWndProc = NULL; } } // virtual event handler public: virtual void OnLangEvent(int nCode, WPARAM wParam, LPARAM lParam) PURE; // data members protected: public: typedef std::list CInstanceList; static CInstanceList s_InstanceList; static HHOOK s_hhookCallWndProc; static CComAutoCriticalSection s_ilCritSec; // call back hook implementation protected: static LRESULT CALLBACK InputLangCallWndProc( int nCode, // hook code WPARAM wParam, // current-process flag LPARAM lParam // message data ) { if (nCode < 0) return ::CallNextHookEx(s_hhookCallWndProc, nCode, wParam, lParam); CWPSTRUCT* pMsg = (CWPSTRUCT*) lParam; switch (pMsg->message) { case WM_INPUTLANGCHANGE: case WM_INPUTLANGCHANGEREQUEST: case WM_INPUTLANGMAGICEVENT: { CComCritSecLock lock(s_ilCritSec); for (CInstanceList::iterator i = s_InstanceList.begin(); i != s_InstanceList.end(); i++) { (*i)->OnLangEvent(nCode, wParam, lParam); } } } return 0; } }; //__declspec(selectany) CComAutoCriticalSection CLangEventListener::s_ilCritSec; CComAutoCriticalSection CLangEventListener::s_ilCritSec; //__declspec(selectany) CLangEventListener::CInstanceList CLangEventListener::s_InstanceList; CLangEventListener::CInstanceList CLangEventListener::s_InstanceList; __declspec(selectany) HHOOK CLangEventListener::s_hhookCallWndProc = NULL;