Browse Source

修复触屏问题

张洋 4 weeks ago
parent
commit
e9f2947fe1
2 changed files with 27 additions and 12 deletions
  1. 23 0
      DuiLib/Core/UIManager.cpp
  2. 4 12
      zhipuzi_pos_windows/ui/CTouchWindowBase.cpp

+ 23 - 0
DuiLib/Core/UIManager.cpp

@@ -1009,6 +1009,29 @@ namespace DuiLib
 	bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)
 	{
 		if (m_hWndPaint == NULL) return false;
+
+		// [触屏兼容修复] 过滤 Windows 为“触摸手势”模拟出来的鼠标消息(ExtraInfo 带 MOUSEEVENTF_FROMTOUCH 标记)。
+		// 背景:调用 RegisterTouchWindow 后,Windows 在把 WM_TOUCH 交给我们的同时,还会“模拟”出一套
+		//   WM_LBUTTONDOWN / WM_LBUTTONMOVE / WM_LBUTTONUP(以及可能的 WM_LBUTTONDBLCLK)。
+		// 这些模拟消息若进入 DuiLib,会导致:
+		//   * 手指刚按下准备滑动就被当成“点击” —— 误把商品加入购物车;
+		//   * 滑动时经过的每个商品 item 都被置上悬浮态(UISTATE_HOT) 且无人清除 —— 多个 item 同时悬浮;
+		//   * 抬起后悬浮态卡死不消失。
+		// 触摸手势的实际处理(滚动 / 轻触判定 / 惯性)由 CTouchWindowBase 通过 WM_TOUCH 完成,
+		// 轻触时它会以“纯净鼠标消息”(ExtraInfo=0) 重新发一次 down+up 给真正需要点击的控件。
+		//
+		// 作用范围用 IsTouchWindow 精确限定:只有调用过 RegisterTouchWindow 的窗口(主窗口及所有模态框,
+		// 均继承自 CTouchWindowBase)才过滤。DuiLib 的下拉框/菜单等弹出窗口并未注册触摸,
+		// IsTouchWindow 返回 FALSE —— 它们的 FROMTOUCH 鼠标照常进入 DuiLib,触摸点选不受影响。
+		if ((uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK
+			|| uMsg == WM_MOUSEMOVE)
+			&& ::IsTouchWindow(m_hWndPaint, NULL)
+			&& (::GetMessageExtraInfo() & 0xFF515700) == 0xFF515700)
+		{
+			lRes = 0;
+			return true; // 标记为已处理,阻止 DuiLib 继续处理
+		}
+
 		// Cycle through listeners
 		for (int i = 0; i < m_aMessageFilters.GetSize(); i++)
 		{

+ 4 - 12
zhipuzi_pos_windows/ui/CTouchWindowBase.cpp

@@ -84,16 +84,6 @@ LRESULT CTouchWindowBase::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 			::RegisterTouchWindow(m_hWnd, 0);
 			break;
 
-		case WM_LBUTTONDOWN:
-		case WM_LBUTTONUP:
-		case WM_LBUTTONDBLCLK:
-			// 关键修复:过滤 Windows 为触屏“模拟”出来的鼠标消息(带 MOUSEEVENTF_FROMTOUCH)。
-			// 否则手指在列表上滑动/轻触都会被当成真实鼠标点击 —— 这正是“滑动误触加入购物车”的根因。
-			// 真实鼠标的 ExtraInfo 不带该标记,因此不影响鼠标操作(含调试鼠标)。
-			if ((::GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH)
-				return 0;
-			break;
-
 		case WM_TOUCH:
 		{
 			UINT cInputs = LOWORD(wParam);
@@ -170,8 +160,10 @@ LRESULT CTouchWindowBase::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 								::PostMessage(target, WM_MOUSEWHEEL, wParamWheel, lParamPos);
 							}
 
-							// 仍然发送鼠标移动,兼容需要拖拽的控件
-							::PostMessage(target, WM_MOUSEMOVE, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
+							// 注意:触摸滚动时不再发送 WM_MOUSEMOVE。原因:
+							//   滚动期间若发 WM_MOUSEMOVE,DuiLib 会给手指扫过的每个 item 置上悬浮态(UISTATE_HOT),
+							//   且触摸抬起后没有 WM_MOUSELEAVE 来清除,导致“多个 item 同时悬浮、且悬停态卡死不消失”。
+							//   滚动本身就由上面的 WM_MOUSEWHEEL 完成,不需要鼠标移动消息;真实鼠标的悬停仍由 DuiLib 正常处理。
 						}
 					}
 					// 触摸抬起