You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
435 lines
9.3 KiB
C++
435 lines
9.3 KiB
C++
2 years ago
|
// XTPMouseManager.cpp : implementation of the CXTPMouseManager class.
|
||
|
//
|
||
|
// This file is a part of the XTREME COMMANDBARS MFC class library.
|
||
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
||
|
//
|
||
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
||
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
||
|
// CONSENT OF CODEJOCK SOFTWARE.
|
||
|
//
|
||
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
||
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
||
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
||
|
// SINGLE COMPUTER.
|
||
|
//
|
||
|
// CONTACT INFORMATION:
|
||
|
// support@codejock.com
|
||
|
// http://www.codejock.com
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "Common/XTPDrawHelpers.h"
|
||
|
#include "Common/XTPSystemHelpers.h"
|
||
|
#include "Common/XTPHookManager.h"
|
||
|
|
||
|
#include "XTPCommandBarsDefines.h"
|
||
|
#include "XTPMouseManager.h"
|
||
|
#include "XTPCommandBar.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
CThreadLocal<CXTPMouseManager> CXTPMouseManager::_xtpMouseThreadState;
|
||
|
static CPoint ptMouse;
|
||
|
|
||
|
|
||
|
#define TID_MOUSELEAVE 113341
|
||
|
|
||
|
CXTPMouseManager::CXTPMouseManager()
|
||
|
{
|
||
|
m_hHookMouse = 0;
|
||
|
m_nLock = 0;
|
||
|
m_hwndLeave = 0;
|
||
|
m_bForceExpanded = FALSE;
|
||
|
m_pSelected = 0;
|
||
|
m_bIgnoreLButtonUp = FALSE;
|
||
|
|
||
|
#ifdef _AFXDLL
|
||
|
m_pModuleState = 0;
|
||
|
#endif
|
||
|
SetupHook(TRUE);
|
||
|
}
|
||
|
|
||
|
CXTPMouseManager::~CXTPMouseManager()
|
||
|
{
|
||
|
SetupHook(FALSE);
|
||
|
}
|
||
|
|
||
|
void CXTPMouseManager::DeliverMessage(CXTPCommandBar* pCapture, WPARAM wParam, POINT pt)
|
||
|
{
|
||
|
if (!pCapture->GetSafeHwnd())
|
||
|
return;
|
||
|
|
||
|
switch (wParam)
|
||
|
{
|
||
|
case WM_MOUSEMOVE:
|
||
|
case WM_NCMOUSEMOVE:
|
||
|
if (pCapture->m_nLockRecurse <= 0)
|
||
|
{
|
||
|
pCapture->ScreenToClient(&pt);
|
||
|
pCapture->OnMouseMove(0, pt);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONDOWN:
|
||
|
case WM_NCLBUTTONDOWN:
|
||
|
case WM_RBUTTONDOWN:
|
||
|
case WM_NCRBUTTONDOWN:
|
||
|
case WM_MBUTTONDOWN:
|
||
|
case WM_NCMBUTTONDOWN:
|
||
|
SendTrackLost();
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONUP:
|
||
|
case WM_NCLBUTTONUP:
|
||
|
if (!IsMouseLocked())
|
||
|
SendTrackLost();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
CXTPCommandBar* CXTPMouseManager::HitTest(POINT point) const
|
||
|
{
|
||
|
HWND hWndMouse = ::WindowFromPoint(point);
|
||
|
const CTrackArray& arrTracked = m_arrTracked;
|
||
|
int i;
|
||
|
|
||
|
for (i = (int)arrTracked.GetSize() - 1; i >= 0; i--)
|
||
|
{
|
||
|
CXTPCommandBar* pCommandBar = arrTracked[i];
|
||
|
|
||
|
if (!pCommandBar->GetSafeHwnd())
|
||
|
continue;
|
||
|
|
||
|
int nHtCode = pCommandBar->OnMouseHitTest(point);
|
||
|
|
||
|
if ((nHtCode != HTERROR) && ((nHtCode == HTCLIENT) || ::IsChild(pCommandBar->GetSafeHwnd(), hWndMouse)))
|
||
|
{
|
||
|
return pCommandBar;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPMouseManager::PreviewTackLost(CXTPCommandBar* pContextMenu, MSG* msg) const
|
||
|
{
|
||
|
if (!(msg->message == WM_LBUTTONDOWN || msg->message == WM_RBUTTONDOWN || msg->message == WM_MBUTTONDOWN ||
|
||
|
msg->message == WM_NCLBUTTONDOWN || msg->message == WM_NCRBUTTONDOWN))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
CPoint point;
|
||
|
GetCursorPos(&point);
|
||
|
|
||
|
CXTPCommandBar* pCommandBar = HitTest(point);
|
||
|
if (pCommandBar)
|
||
|
{
|
||
|
if (pCommandBar->m_nLockRecurse == 0 || pContextMenu->m_nLockRecurse != 0)
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
HWND hWndMouse = ::WindowFromPoint(point);
|
||
|
|
||
|
if (m_arrTracked.GetSize() > 0)
|
||
|
{
|
||
|
const CTrustedArray& arrTrusted = m_arrTrusted;
|
||
|
for (int i = 0; i < arrTrusted.GetSize(); i++)
|
||
|
{
|
||
|
HWND hWnd = arrTrusted[i];
|
||
|
if (IsWindow(hWnd) && IsWindowVisible(hWnd) && CXTPWindowRect(hWnd).PtInRect(point))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (hWndMouse)
|
||
|
{
|
||
|
if (GetClassLong(hWndMouse, GCL_STYLE) & CS_IME)
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPMouseManager::IsRelated(HWND hWndParent, HWND hWnd) const
|
||
|
{
|
||
|
hWnd = ::GetParent(hWnd);
|
||
|
|
||
|
while (hWnd)
|
||
|
{
|
||
|
if (hWnd == hWndParent)
|
||
|
return TRUE;
|
||
|
|
||
|
hWnd = ::GetParent(hWnd);
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPMouseManager::PreTranslateMouseEvents(WPARAM wParam, POINT point)
|
||
|
{
|
||
|
HWND hWndMouse = ::WindowFromPoint(point);
|
||
|
CTrackArray& arrTracked = m_arrTracked;
|
||
|
int i;
|
||
|
|
||
|
for (i = (int)arrTracked.GetSize() - 1; i >= 0; i--)
|
||
|
{
|
||
|
CXTPCommandBar* pCommandBar = arrTracked[i];
|
||
|
|
||
|
if (!pCommandBar->GetSafeHwnd())
|
||
|
continue;
|
||
|
|
||
|
int nHtCode = pCommandBar->OnMouseHitTest(point);
|
||
|
|
||
|
if ((nHtCode != HTERROR) && ((nHtCode == HTCLIENT) || ::IsChild(pCommandBar->GetSafeHwnd(), hWndMouse) || IsRelated(pCommandBar->GetSafeHwnd(), hWndMouse)))
|
||
|
{
|
||
|
if (pCommandBar->m_nLockRecurse > 0 && wParam != WM_MOUSEMOVE && wParam != WM_NCMOUSEMOVE && !m_bIgnoreLButtonUp)
|
||
|
{
|
||
|
SendTrackLostRecurse();
|
||
|
ptMouse = 0;
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (arrTracked.GetSize() > 0)
|
||
|
{
|
||
|
CTrustedArray& arrTrusted = m_arrTrusted;
|
||
|
for (i = 0; i < arrTrusted.GetSize(); i++)
|
||
|
{
|
||
|
HWND hWnd = arrTrusted[i];
|
||
|
if (IsWindow(hWnd) && IsWindowVisible(hWnd) && CXTPWindowRect(hWnd).PtInRect(point))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (hWndMouse && arrTracked.GetSize() > 0)
|
||
|
{
|
||
|
if (GetClassLong(hWndMouse, GCL_STYLE) & CS_IME)
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < arrTracked.GetSize(); i++)
|
||
|
{
|
||
|
DeliverMessage(arrTracked.GetAt(i), wParam, point);
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
LRESULT CALLBACK CXTPMouseManager::MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
CXTPMouseManager* pMouseManager = XTPMouseManager();
|
||
|
|
||
|
if (nCode != HC_ACTION)
|
||
|
return CallNextHookEx(pMouseManager->m_hHookMouse, nCode, wParam, lParam);
|
||
|
|
||
|
PMOUSEHOOKSTRUCT pHook = (PMOUSEHOOKSTRUCT)lParam;
|
||
|
CPoint point = pHook->pt;
|
||
|
|
||
|
CTrackArray& arrTracked = pMouseManager->m_arrTracked;
|
||
|
|
||
|
if (wParam == WM_LBUTTONDOWN || wParam == WM_RBUTTONDOWN)
|
||
|
pMouseManager->m_bIgnoreLButtonUp = FALSE;
|
||
|
|
||
|
if ((wParam == WM_LBUTTONUP || wParam == WM_NCLBUTTONUP) && pMouseManager->m_bIgnoreLButtonUp)
|
||
|
{
|
||
|
pMouseManager->m_bIgnoreLButtonUp = FALSE;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (arrTracked.GetSize() != 0 && (wParam == WM_MOUSEMOVE || wParam == WM_NCMOUSEMOVE) && ptMouse == point)
|
||
|
return TRUE;
|
||
|
|
||
|
ptMouse = point;
|
||
|
|
||
|
if (pMouseManager->m_arrTracked.GetSize() == 0)
|
||
|
return CallNextHookEx(pMouseManager->m_hHookMouse, nCode, wParam, lParam);
|
||
|
|
||
|
SAFE_MANAGE_STATE(pMouseManager->m_pModuleState);
|
||
|
|
||
|
if (pMouseManager->PreTranslateMouseEvents(wParam, point))
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return CallNextHookEx(pMouseManager->m_hHookMouse, nCode, wParam, lParam);
|
||
|
|
||
|
}
|
||
|
|
||
|
void CXTPMouseManager::SetupHook(BOOL bHook)
|
||
|
{
|
||
|
if (bHook && m_hHookMouse == 0)
|
||
|
{
|
||
|
m_hHookMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, 0, GetCurrentThreadId ());
|
||
|
}
|
||
|
if (!bHook && m_hHookMouse)
|
||
|
{
|
||
|
UnhookWindowsHookEx(m_hHookMouse);
|
||
|
m_hHookMouse = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CXTPMouseManager::SetTrack(CXTPCommandBar* pTrack, BOOL /*bCaptureMouse*/)
|
||
|
{
|
||
|
#ifdef _AFXDLL
|
||
|
m_pModuleState = AfxGetModuleState();
|
||
|
#endif
|
||
|
|
||
|
if (m_arrTracked.GetSize() == 0 && m_pSelected && m_pSelected != pTrack)
|
||
|
m_pSelected->OnTrackEnter();
|
||
|
|
||
|
if (m_arrTracked.Find(pTrack) == -1)
|
||
|
m_arrTracked.Add(pTrack);
|
||
|
}
|
||
|
void CXTPMouseManager::RemoveTrack(CXTPCommandBar* pTrack)
|
||
|
{
|
||
|
int nIndex = m_arrTracked.Find(pTrack);
|
||
|
if (nIndex != -1)
|
||
|
{
|
||
|
m_arrTracked.RemoveAt(nIndex);
|
||
|
}
|
||
|
if (m_arrTracked.GetSize() == 0)
|
||
|
{
|
||
|
RefreshCursor();
|
||
|
}
|
||
|
m_bIgnoreLButtonUp = FALSE;
|
||
|
}
|
||
|
|
||
|
void AFX_CDECL CXTPMouseManager::RefreshCursor()
|
||
|
{
|
||
|
ptMouse = CPoint(-1, -1);
|
||
|
|
||
|
CPoint pt;
|
||
|
GetCursorPos(&pt);
|
||
|
SetCursorPos(pt.x, pt.y);
|
||
|
}
|
||
|
|
||
|
|
||
|
void CXTPMouseManager::SendTrackLost()
|
||
|
{
|
||
|
while (m_arrTracked.GetSize() > 0)
|
||
|
{
|
||
|
m_arrTracked[0]->OnTrackLost();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL CXTPMouseManager::IsTopParentActive(HWND hWnd)
|
||
|
{
|
||
|
return CXTPDrawHelpers::IsTopParentActive(hWnd);
|
||
|
}
|
||
|
|
||
|
void CALLBACK CXTPMouseManager::TrackMouseTimerProc (HWND hWnd, UINT /*uMsg*/, UINT idEvent, DWORD /*dwTime*/)
|
||
|
{
|
||
|
RECT rect;
|
||
|
POINT pt;
|
||
|
|
||
|
if (!IsWindow(hWnd))
|
||
|
{
|
||
|
KillTimer (hWnd, idEvent);
|
||
|
XTPMouseManager()->m_hwndLeave = 0;
|
||
|
return;
|
||
|
}
|
||
|
GetWindowRect(hWnd, &rect);
|
||
|
::GetCursorPos (&pt);
|
||
|
|
||
|
BOOL bTopParentActive = GetParent(hWnd) == 0 || (GetWindowLong(hWnd, GWL_STYLE) & WS_POPUP) || IsTopParentActive(hWnd);
|
||
|
if (!::PtInRect (&rect, pt) || !bTopParentActive)
|
||
|
{
|
||
|
KillTimer (hWnd, idEvent);
|
||
|
XTPMouseManager()->m_hwndLeave = 0;
|
||
|
|
||
|
::PostMessage (hWnd, WM_MOUSELEAVE, 0, 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
void CXTPMouseManager::TrackMouseLeave(HWND hwnd)
|
||
|
{
|
||
|
if (m_hwndLeave == hwnd) return;
|
||
|
if (m_hwndLeave && hwnd != m_hwndLeave && IsWindow(m_hwndLeave))
|
||
|
SendMessage(m_hwndLeave, WM_MOUSELEAVE, 0, 0);
|
||
|
m_hwndLeave = hwnd;
|
||
|
::SetTimer (hwnd, TID_MOUSELEAVE, 50,
|
||
|
(TIMERPROC) TrackMouseTimerProc);
|
||
|
}
|
||
|
|
||
|
|
||
|
void CXTPMouseManager::AddTrustedWindow(HWND hWnd)
|
||
|
{
|
||
|
m_arrTrusted.Add(hWnd);
|
||
|
}
|
||
|
void CXTPMouseManager::RemoveTrustedWindow(HWND hWnd)
|
||
|
{
|
||
|
m_arrTrusted.Remove(hWnd);
|
||
|
}
|
||
|
|
||
|
void CXTPMouseManager::LockTrackRecurse(BOOL bLockTrack)
|
||
|
{
|
||
|
for (int i = 0; i < (int)m_arrTracked.GetSize(); i++)
|
||
|
{
|
||
|
m_arrTracked[i]->m_nLockRecurse += bLockTrack ? +1 : -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CXTPCommandBar* CXTPMouseManager::GetTopTracked() const
|
||
|
{
|
||
|
if (m_arrTracked.GetSize() == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
return m_arrTracked.GetAt(m_arrTracked.GetSize() - 1);
|
||
|
}
|
||
|
|
||
|
BOOL CXTPMouseManager::IsTrackedLock(const CXTPCommandBar* pItem /*= NULL*/)
|
||
|
{
|
||
|
if (m_arrTracked.GetSize() == NULL)
|
||
|
return FALSE;
|
||
|
|
||
|
if (pItem == NULL)
|
||
|
return TRUE;
|
||
|
|
||
|
if (pItem->m_nLockRecurse > 0)
|
||
|
return TRUE;
|
||
|
|
||
|
return m_arrTracked.Find(pItem) == -1;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPMouseManager::IsTrackedLockRecurse() const
|
||
|
{
|
||
|
if (m_arrTracked.GetSize() == 0)
|
||
|
return FALSE;
|
||
|
|
||
|
return m_arrTracked[0]->m_nLockRecurse > 0;
|
||
|
}
|
||
|
|
||
|
void CXTPMouseManager::SendTrackLostRecurse()
|
||
|
{
|
||
|
if (m_arrTracked.GetSize() == 0)
|
||
|
return;
|
||
|
|
||
|
BOOL bLocked = m_arrTracked[0]->m_nLockRecurse > 0;
|
||
|
|
||
|
if (bLocked)
|
||
|
for (int i = 0; i < (int)m_arrTracked.GetSize(); i++)
|
||
|
{
|
||
|
if (m_arrTracked[i]->m_nLockRecurse == 0)
|
||
|
m_arrTracked[i]->OnTrackLost();
|
||
|
}
|
||
|
}
|