Click here to Skip to main content
15,891,951 members
Articles / Desktop Programming / MFC

Thunking MouseProc in IE add-in

Rate me:
Please Sign up or sign in to vote.
4.38/5 (7 votes)
3 Nov 20044 min read 70.5K   1K   41  
An article on thunking MouseProc in IE add-in using BHO.
#include "stdafx.h"
#include "MouseTracerManagerImpl5.h"
#include <commctrl.h>


#define IE_STATUSBAR_CID	0x0000A001

HWND FindStatusBarHandle(HWND hActiveWnd)
{
	HWND hWnd = hActiveWnd ? hActiveWnd : ::GetActiveWindow();
	HWND hDesktopWnd = ::GetDesktopWindow();

	HWND hMainWnd = hWnd;
	while( hWnd && hWnd != hDesktopWnd )
	{
		hMainWnd = hWnd;
		hWnd = ::GetParent(hWnd);
	}

	return ::GetDlgItem(hMainWnd, IE_STATUSBAR_CID);
}

LPTSTR szLButtonDown = _T("[ Left Mouse Button Down ]");
LPTSTR szMButtonDown = _T("[ Middle Mouse Button Down ]");
LPTSTR szRButtonDown = _T("[ Right Mouse Button Down ]");
LPTSTR szLButtonDblClk = _T("[ Left Mouse Button DblClk ]");
LPTSTR szMButtonDblClk = _T("[ Middle Mouse Button DblClk ]");
LPTSTR szRButtonDblClk = _T("[ Right Mouse Button DblClk ]");
LPTSTR szWheel = _T("[ Mouse Wheel Up/Down ]");

#ifndef WM_MOUSEWHEEL

#define WM_MOUSEWHEEL                   0x020A

#endif	// #ifndef WM_MOUSEWHEEL

CMouseTracerManagerImpl5::CMouseProcHook::CMouseProcHook() : m_hHook(NULL), m_lParam(0)
{
}

CMouseTracerManagerImpl5::CMouseProcHook::~CMouseProcHook()
{
	if(m_hHook)
		::UnhookWindowsHookEx(m_hHook);
}

BOOL CMouseTracerManagerImpl5::CMouseProcHook::SetMouseProcHook(HINSTANCE hmod, DWORD dwThreadID)
{
	m_thunk.Init(CMouseTracerManagerImpl5::MouseProc, this);
	m_hHook = ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)&(m_thunk.thunk), hmod, dwThreadID);
	if(NULL == m_hHook)
		::MessageBox(NULL, _T("Failed to set up the Mouse Hook"), _T("DragIt Error"), MB_OK | MB_ICONERROR);
	ATLTRACE(_T("\n\n::SetWindowsHookEx(), HINSTANCE=(%x),TID=(%x),&thunk=(%x),HHOOK=(%x)\n\n\n"), hmod, dwThreadID, &(m_thunk.thunk), m_hHook);

	return (NULL != m_hHook);
}

void CMouseTracerManagerImpl5::CMouseProcHook::UnhookMouseProcHook()
{
	if(m_hHook)
	{
		ATLTRACE(_T("\n\n::UnhookWindowsHookEx(), TID=(%x), HHOOK=(%x)\n\n\n"), ::GetCurrentThreadId(), m_hHook);
		::UnhookWindowsHookEx(m_hHook);
		m_hHook = NULL;
	}
}
			
CMouseTracerManagerImpl5::CMouseProcHookMap CMouseTracerManagerImpl5::m_mouseProcHookMap;

CMouseTracerManagerImpl5::CMouseTracerManagerImpl5()
{	
}

CMouseTracerManagerImpl5::~CMouseTracerManagerImpl5()
{
	std::for_each<CMouseTracerManagerImpl5::CMouseProcHookMap::iterator>(
		m_mouseProcHookMap.begin(),
		m_mouseProcHookMap.end(),
		CMouseTracerManagerImpl5::CMouseProcHookMap::DeleteAndNull() );

	m_mouseProcHookMap.clear();
}

BOOL CMouseTracerManagerImpl5::Setup(HINSTANCE hMod/* = NULL*/, DWORD dwThreadID/* = 0*/)
{
	if(0 == dwThreadID)
		dwThreadID = ::GetCurrentThreadId();
	CMouseTracerManagerImpl5::CMouseProcHookMap::iterator itMap = m_mouseProcHookMap.find(dwThreadID);
	if(m_mouseProcHookMap.end() != itMap)
		return TRUE;	// the mouse hook is already installed for the specific thread

	CMouseTracerManagerImpl5::CMouseProcHook *pMouseProcHook = new CMouseTracerManagerImpl5::CMouseProcHook;
	BOOL bReturn = pMouseProcHook->SetMouseProcHook(hMod, dwThreadID);
	if(bReturn)
		m_mouseProcHookMap[dwThreadID] = (LPVOID)pMouseProcHook;
	
	return bReturn;
}

void CMouseTracerManagerImpl5::Remove(DWORD dwThreadID/* = 0*/)
{
	if(0 == dwThreadID)
		dwThreadID = ::GetCurrentThreadId();
	CMouseTracerManagerImpl5::CMouseProcHookMap::iterator itMap = m_mouseProcHookMap.find(dwThreadID);
	if(m_mouseProcHookMap.end() != itMap)
	{
		if(itMap->second)
			((CMouseProcHook *)itMap->second)->UnhookMouseProcHook();
		delete itMap->second;
		m_mouseProcHookMap.erase(itMap);
	}
}

LRESULT CALLBACK CMouseTracerManagerImpl5::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	CMouseProcHook *pThis = reinterpret_cast<CMouseProcHook *>(lParam);
	lParam = pThis->GetLPARAM();
	
    if (nCode == HC_ACTION)
    {
        if (lParam)
        {
			
#if(_WIN32_WINNT >= 0x0500)
			
            MOUSEHOOKSTRUCTEX *pMHEX = reinterpret_cast<MOUSEHOOKSTRUCTEX *>(lParam);
			MOUSEHOOKSTRUCT *pMH = (MOUSEHOOKSTRUCT *)pMHEX;
			
#else	// #if(_WIN32_WINNT >= 0x0500)
			
            MOUSEHOOKSTRUCT *pMH = reinterpret_cast<MOUSEHOOKSTRUCT *>(lParam);
			
#endif	// #if(_WIN32_WINNT >= 0x0500)

			pMH;
			ATLASSERT(pMH);
			
			DWORD dwRes = 0;
			switch (wParam)
			{
			case WM_LBUTTONDOWN:
				::SendMessageTimeout(
					FindStatusBarHandle(pMH->hwnd),
					SB_SETTEXT,
					(WPARAM)0,
					(LPARAM)(LPSTR)szLButtonDown,
					SMTO_ABORTIFHUNG,
					1000,
					&dwRes);
				break;

			case WM_MBUTTONDOWN:
				::SendMessageTimeout(
					FindStatusBarHandle(pMH->hwnd),
					SB_SETTEXT,
					(WPARAM)0,
					(LPARAM)(LPSTR)szMButtonDown,
					SMTO_ABORTIFHUNG,
					1000,
					&dwRes);
				break;
				
			case WM_RBUTTONDOWN:
				::SendMessageTimeout(
					FindStatusBarHandle(pMH->hwnd),
					SB_SETTEXT,
					(WPARAM)0,
					(LPARAM)(LPSTR)szRButtonDown,
					SMTO_ABORTIFHUNG,
					1000,
					&dwRes);
				break;
				
			case WM_LBUTTONDBLCLK:
				::SendMessageTimeout(
					FindStatusBarHandle(pMH->hwnd),
					SB_SETTEXT,
					(WPARAM)0,
					(LPARAM)(LPSTR)szLButtonDblClk,
					SMTO_ABORTIFHUNG,
					1000,
					&dwRes);
				break;
				
			case WM_MBUTTONDBLCLK:
				::SendMessageTimeout(
					FindStatusBarHandle(pMH->hwnd),
					SB_SETTEXT,
					(WPARAM)0,
					(LPARAM)(LPSTR)szMButtonDblClk,
					SMTO_ABORTIFHUNG,
					1000,
					&dwRes);
				break;
				
			case WM_RBUTTONDBLCLK:
				::SendMessageTimeout(
					FindStatusBarHandle(pMH->hwnd),
					SB_SETTEXT,
					(WPARAM)0,
					(LPARAM)(LPSTR)szRButtonDblClk,
					SMTO_ABORTIFHUNG,
					1000,
					&dwRes);
				break;

			case WM_MOUSEWHEEL:
				::SendMessageTimeout(
					FindStatusBarHandle(pMH->hwnd),
					SB_SETTEXT,
					(WPARAM)0,
					(LPARAM)(LPSTR)szWheel,
					SMTO_ABORTIFHUNG,
					1000,
					&dwRes);
				break;
				
			default:
				break;
			}
		}
    }
	
	return ::CallNextHookEx(pThis->GetHHOOK(), nCode, wParam, lParam);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Other
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions