#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);
}