|
|
@@ -588,7 +588,9 @@ namespace DuiLib
|
|
|
// 走 MessageHandler 里原生的鼠标点击路径(CButtonUI 等据此 Activate())。NIM 从不过滤
|
|
|
// 这些模拟鼠标,只在 WM_LBUTTON* 分支加了 m_pEventTouch!=NULL 守卫,保证一次手指手势
|
|
|
// 要么滚动、要么点击,不会双触发。
|
|
|
- // 4) 守卫:若 m_pEventClick 已存在(鼠标/指针交互进行中),直接忽略本次触摸,互不打架。
|
|
|
+ // 4) 守卫:DOWN 时若真实鼠标已在交互(m_pEventClick 被真实鼠标置位)则忽略触摸;MOVE 仅对“滚动条”让路
|
|
|
+ // (原生鼠标独占滑块拖拽),容器照常收 TOUCHMOVE 跟手滚动。注意 m_pEventClick 也会被触摸模拟的
|
|
|
+ // WM_LBUTTONDOWN 置位,故不能仅因它非空就吞掉 TOUCHMOVE,否则列表滚不动。
|
|
|
TouchApi::PFN_GetTouchInputInfo pfnGetInfo = TouchApi::GetGetTouchInputInfo();
|
|
|
if (pfnGetInfo == NULL) return;
|
|
|
|
|
|
@@ -644,8 +646,12 @@ namespace DuiLib
|
|
|
}
|
|
|
else if (ti.dwFlags & TouchApi::TOUCHEVTFLAG_MOVE)
|
|
|
{
|
|
|
- // 鼠标/指针交互进行中 -> 忽略触摸
|
|
|
- if (m_pEventClick != NULL) break;
|
|
|
+ // 鼠标/指针交互进行中 -> 忽略触摸。但注意:一次触摸手势本身会触发 Windows 模拟的
|
|
|
+ // WM_LBUTTONDOWN,从而把 m_pEventClick 置为【当前命中控件】(容器/按钮/滚动条都会)。
|
|
|
+ // 若整句 break,会把容器的 UIEVENT_TOUCHMOVE 一起吞掉→列表无法跟手滚动。
|
|
|
+ // 故只对“滚动条”让路(滚动条滑块拖拽由原生鼠标驱动,见 DOWN 的 ScrollBar break),
|
|
|
+ // 其余控件(容器/按钮)照常派发 TOUCHMOVE:容器据此 1:1 跟手滚动,按钮不处理 TOUCHMOVE 无害。
|
|
|
+ if (m_pEventClick != NULL && m_pEventClick->GetInterface(_T("ScrollBar")) != NULL) break;
|
|
|
// 与上一包完全相同的点 -> 去重,避免无谓派发(NIM 同款守卫)
|
|
|
if (m_ptLastTouchPos.x == pt.x && m_ptLastTouchPos.y == pt.y) break;
|
|
|
// 本次位移增量(相对上一包),随事件下发,滚动容器据此做 1:1 跟手平移
|
|
|
@@ -673,18 +679,38 @@ namespace DuiLib
|
|
|
{
|
|
|
m_ptLastTouchPos = pt;
|
|
|
|
|
|
- // 触屏抬起模拟“鼠标离开”:清除悬浮态。触摸不会生成 WM_MOUSELEAVE,
|
|
|
- // 否则按钮/列表项点击后悬浮态残留。滚动条等提前退出的触点 m_pEventTouch 为 NULL,同样要清。
|
|
|
- if (m_pEventHover != NULL)
|
|
|
+ // 触屏抬起模拟“鼠标离开”:清除悬浮态。触摸永远不会生成 WM_MOUSELEAVE,
|
|
|
+ // 若只清 m_pEventHover,m_aNeedMouseLeaveNeeded 数组里登记过的控件
|
|
|
+ // (按钮/列表项/滚动条等曾收到 MOUSEENTER 并 AddMouseLeaveNeeded 的)会一直残留
|
|
|
+ // 悬浮态,表现为“多个控件同时悬浮”。必须复刻 WM_MOUSEMOVE 里的离开广播:先遍历
|
|
|
+ // 整个数组逐一发 MOUSELEAVE(控件自身在 MOUSELEAVE 里把自己从数组移除),再清 m_pEventHover。
|
|
|
+ if (m_aNeedMouseLeaveNeeded.GetSize() > 0 || m_pEventHover != NULL)
|
|
|
{
|
|
|
TEventUI event = { 0 };
|
|
|
event.Type = UIEVENT_MOUSELEAVE;
|
|
|
- event.pSender = m_pEventHover;
|
|
|
event.ptMouse = pt;
|
|
|
event.wKeyState = MapKeyState();
|
|
|
event.dwTimestamp = ::GetTickCount();
|
|
|
- m_pEventHover->Event(event);
|
|
|
- m_pEventHover = NULL;
|
|
|
+
|
|
|
+ if (m_aNeedMouseLeaveNeeded.GetSize() > 0)
|
|
|
+ {
|
|
|
+ CStdPtrArray aNeedMouseLeaveNeeded(m_aNeedMouseLeaveNeeded.GetSize());
|
|
|
+ aNeedMouseLeaveNeeded.Resize(m_aNeedMouseLeaveNeeded.GetSize());
|
|
|
+ ::CopyMemory(aNeedMouseLeaveNeeded.GetData(), m_aNeedMouseLeaveNeeded.GetData(), m_aNeedMouseLeaveNeeded.GetSize() * sizeof(LPVOID));
|
|
|
+ for (int i = 0; i < aNeedMouseLeaveNeeded.GetSize(); i++)
|
|
|
+ {
|
|
|
+ CControlUI* pHover = static_cast<CControlUI*>(aNeedMouseLeaveNeeded[i]);
|
|
|
+ event.pSender = pHover;
|
|
|
+ pHover->Event(event);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (m_pEventHover != NULL)
|
|
|
+ {
|
|
|
+ event.pSender = m_pEventHover;
|
|
|
+ m_pEventHover->Event(event);
|
|
|
+ m_pEventHover = NULL;
|
|
|
+ }
|
|
|
+ if (m_hwndTooltip != NULL) ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM)&m_ToolTip);
|
|
|
}
|
|
|
|
|
|
// 滚动条等场景本函数未接管(m_pEventTouch 为 NULL),捕获由原生鼠标路径负责,这里不释放。
|
|
|
@@ -2072,8 +2098,11 @@ namespace DuiLib
|
|
|
break;
|
|
|
case WM_LBUTTONUP:
|
|
|
{
|
|
|
- // 触屏拖拽手势(已发生位移)-> 松开不触发点击,仅滚动(避免“拖拽又误点”)
|
|
|
- if (m_bTouchMoved) m_pEventClick = NULL;
|
|
|
+ // 触屏拖拽手势(已发生位移)-> 松开不触发“点击”,避免“拖拽又误点”。
|
|
|
+ // 但滚动条滑块拖拽依赖 BUTTONUP 来解除 UISTATE_CAPTURED 并停掉 50ms 定时器,
|
|
|
+ // 绝不能在此提前清空 m_pEventClick,否则滚动条卡死在捕获态。故对滚动条放行 BUTTONUP。
|
|
|
+ if (m_bTouchMoved && m_pEventClick != NULL && m_pEventClick->GetInterface(_T("ScrollBar")) == NULL)
|
|
|
+ m_pEventClick = NULL;
|
|
|
m_bTouchMoved = false; // 用完即清,绝不影响后续真实鼠标点击
|
|
|
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
|
|
|
m_ptLastMousePos = pt;
|