张洋 4 weeks ago
parent
commit
d24cd0779d
2 changed files with 18 additions and 4 deletions
  1. 16 4
      DuiLib/Core/UIManager.cpp
  2. 2 0
      DuiLib/Core/UIManager.h

+ 16 - 4
DuiLib/Core/UIManager.cpp

@@ -20,7 +20,7 @@ namespace DuiLib
 	// tap slop:手指位移超过该距离即判为滑动手势,抬起时不再产生点击。
 	// NIM 原实现只靠「抬起点是否仍落在控件内」来判定是否 click;此处额外加滑动阈值,
 	// 是因为 POS 收银场景下手指微颤/小幅拖动极易被判成点击,从而误把商品加进购物车。
-	static constexpr LONG TOUCH_TAP_SLOP = 10;
+	static constexpr LONG TOUCH_TAP_SLOP = 16;
 
 	// WM_TOUCH 消息 ID 同样受 `#if _WIN32_WINNT >= 0x0601` 保护,DuiLib 工程未定义
 	// _WIN32_WINNT(StdAfx.h 兜底为 XP)→ 必须自行声明,否则 switch 里引用该消息 ID
@@ -659,12 +659,24 @@ namespace DuiLib
 				LONG netDx = pt.x - m_ptTouchDownPos.x;
 				LONG netDy = pt.y - m_ptTouchDownPos.y;
 				m_moveDistSq = (std::int64_t)netDx * netDx + (std::int64_t)netDy * netDy;
-				if (m_moveDistSq > (std::int64_t)TOUCH_TAP_SLOP * TOUCH_TAP_SLOP)
-					m_bTouchMoved = true;
+
+				if (!m_bTouchMoved)
+				{
+					if (m_moveDistSq > (std::int64_t)TOUCH_TAP_SLOP * TOUCH_TAP_SLOP)
+					{
+						// 越过“轻触死区”-> 判定为滑动。吞掉越过死区这一包的移动量,
+						// 让滚动从死区边界干净起步,避免突然跳动;后续包才真正跟手滚动。
+						m_bTouchMoved = true;
+						continue;
+					}
+					// 仍在轻触死区内:吸收位移,不滚动、不派发 TOUCHMOVE
+					// (否则“点一下不滑动”也会被抖动的 MOVE 包驱动成滚动,且抬起时点击被吞掉)。
+					continue;
+				}
 
 				if (dx == 0 && dy == 0) continue;
 
-				// 派发给当前触点下的控件。绝大多数控件不认 UIEVENT_TOUCHMOVE,
+				// 滑动已确认:派发给当前触点下的控件。绝大多数控件不认 UIEVENT_TOUCHMOVE,
 				// 会沿 CControlUI::DoEvent 末尾的 m_pParent->DoEvent 天然冒泡到最近的滚动容器
 				// (等价于 NIM 里 ScrollableBox 收到 kEventTouchMove),由它做 1:1 跟手平移。
 				CControlUI* pTarget = FindControl(pt);

+ 2 - 0
DuiLib/Core/UIManager.h

@@ -476,6 +476,8 @@ namespace DuiLib {
 		//   UP   → UIEVENT_BUTTONUP(归一化)   控件按原生鼠标语义处理抬起(按钮 PtInRect 通过才 Activate → click)
 		// 全程不合成任何鼠标消息(已废弃 SynthesizeTap):点击由控件 Activate()+SendNotify 直接产生,
 		// 不经过 Windows 消息队列,所以主窗口与模态弹框行为完全一致。
+		// MOVE 在“轻触死区”(TOUCH_TAP_SLOP=16px 净位移)内被吸收,不派发 TOUCHMOVE,避免“点一下就滚动”;
+		// 越过后才判定为滑动并跟手滚动,抬起时 ptMouse 设 (-1,-1) 抑制误触 click。
 		// 注册在 Init 中完成,无需逐窗口样板,也无需 CTouchWindowBase 外挂。
 		void InitTouchSupport();
 		void OnTouchInput(WPARAM wParam, LPARAM lParam);