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;