Browse Source

先保存一下这个版本,主窗口点击、滑动正常,就是模态对话框还不正常。

张洋 3 weeks ago
parent
commit
f09f8172f7
2 changed files with 51 additions and 13 deletions
  1. 50 13
      DuiLib/Core/UIManager.cpp
  2. 1 0
      DuiLib/Core/UIManager.h

+ 50 - 13
DuiLib/Core/UIManager.cpp

@@ -36,7 +36,6 @@ namespace DuiLib
 #ifndef WM_TOUCH
 #ifndef WM_TOUCH
 #define WM_TOUCH 0x0240
 #define WM_TOUCH 0x0240
 #endif
 #endif
-
 	// ---------------------------------------------------------------------------
 	// ---------------------------------------------------------------------------
 	// [触屏诊断] 保留日志入口以便后续定位,但当前默认关闭。
 	// [触屏诊断] 保留日志入口以便后续定位,但当前默认关闭。
 	// ---------------------------------------------------------------------------
 	// ---------------------------------------------------------------------------
@@ -44,7 +43,7 @@ namespace DuiLib
 	{
 	{
 		inline bool Enabled()
 		inline bool Enabled()
 		{
 		{
-			return false;
+				return true;
 		}
 		}
 
 
 		// 极简 TCHAR* → UTF-8 char* 转换(仅用于日志路径;非线程安全,够用即可)
 		// 极简 TCHAR* → UTF-8 char* 转换(仅用于日志路径;非线程安全,够用即可)
@@ -735,8 +734,13 @@ namespace DuiLib
 		if (m_hWndPaint == NULL || !::IsWindow(m_hWndPaint)) return;
 		if (m_hWndPaint == NULL || !::IsWindow(m_hWndPaint)) return;
 
 
 		TouchApi::PFN_RegisterTouchWindow pfnRegister = TouchApi::GetRegisterTouchWindow();
 		TouchApi::PFN_RegisterTouchWindow pfnRegister = TouchApi::GetRegisterTouchWindow();
+		BOOL bRegistered = FALSE;
 		if (pfnRegister != NULL)
 		if (pfnRegister != NULL)
-			pfnRegister(m_hWndPaint, 0);
+			bRegistered = pfnRegister(m_hWndPaint, 0);
+		TouchTrace::Log(_T("REGISTER hwnd=%p manager=%p result=%d error=%u style=0x%08X ex=0x%08X"),
+			(void*)m_hWndPaint, (void*)this, (int)bRegistered, bRegistered ? 0u : ::GetLastError(),
+			(unsigned)::GetWindowLong(m_hWndPaint, GWL_STYLE),
+			(unsigned)::GetWindowLong(m_hWndPaint, GWL_EXSTYLE));
 	}
 	}
 
 
 	void CPaintManagerUI::OnTouchInput(WPARAM wParam, LPARAM lParam)
 	void CPaintManagerUI::OnTouchInput(WPARAM wParam, LPARAM lParam)
@@ -1017,6 +1021,7 @@ namespace DuiLib
 
 
 				m_pEventTouch = NULL;
 				m_pEventTouch = NULL;
 				m_pTouchScrollContainer = NULL;
 				m_pTouchScrollContainer = NULL;
+				m_bSuppressPromotedTouchMouse = true;
 			}
 			}
 		}
 		}
 
 
@@ -1622,14 +1627,26 @@ namespace DuiLib
 	bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)
 	bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)
 	{
 	{
 		if (m_hWndPaint == NULL) return false;
 		if (m_hWndPaint == NULL) return false;
+		if (uMsg == WM_TOUCH || uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
+		{
+			TouchTrace::Log(_T("MANAGER-MSG hwnd=%p manager=%p msg=0x%04X w=0x%p l=0x%p touch=%p suppress=%d"),
+				(void*)m_hWndPaint, (void*)this, uMsg, (void*)wParam, (void*)lParam,
+				(void*)m_pEventTouch, (int)m_bSuppressPromotedTouchMouse);
+		}
 
 
-		// 触摸点击由 WM_TOUCH 直接驱动 BUTTONDOWN/BUTTONUP。
-		// 部分收银机仍会补发鼠标消息,但这些消息不能再次进入普通鼠标状态机,
-		// 否则会造成重复点击或覆盖触摸手势状态。
-		if ((uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK)
-			&& IsPromotedTouchMouseMessage())
+		// 触摸点击优先由 WM_TOUCH 状态机驱动 BUTTONDOWN/BUTTONUP。
+		// 只有当前 manager 已经收到本次 WM_TOUCH,或刚刚完成了触摸点击,
+		// 才拦截随后提升的鼠标消息。不能仅凭 FROMTOUCH 标记无条件拦截,
+		// 因为部分模态窗口只收到 Windows 提升的鼠标消息而没有收到 WM_TOUCH,
+		// 无条件拦截会导致模态窗口完全无法触摸点击。
+		if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK)
 		{
 		{
-			return true;
+			if (m_pEventTouch != NULL || m_bSuppressPromotedTouchMouse)
+			{
+				if (uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK)
+					m_bSuppressPromotedTouchMouse = false;
+				return true;
+			}
 		}
 		}
 
 
 		// [触屏兼容] 不再过滤 Windows 为触摸模拟的鼠标消息(MOUSEEVENTF_FROMTOUCH)。
 		// [触屏兼容] 不再过滤 Windows 为触摸模拟的鼠标消息(MOUSEEVENTF_FROMTOUCH)。
@@ -2430,7 +2447,7 @@ namespace DuiLib
 					m_pEventClick != NULL ? m_pEventClick->GetName().GetData() : _T("null"));
 					m_pEventClick != NULL ? m_pEventClick->GetName().GetData() : _T("null"));
 				// WM_TOUCH 后 Windows 可能补发 WM_LBUTTONDOWN。触摸点击由 TOUCHUP
 				// WM_TOUCH 后 Windows 可能补发 WM_LBUTTONDOWN。触摸点击由 TOUCHUP
 				// 的 tap 判定统一处理,不能让这条合成消息提前建立鼠标点击状态。
 				// 的 tap 判定统一处理,不能让这条合成消息提前建立鼠标点击状态。
-				if (m_pEventTouch != NULL)
+				if (m_pEventTouch != NULL || m_bSuppressPromotedTouchMouse)
 					break;
 					break;
 				// We alway set focus back to our app (this helps
 				// We alway set focus back to our app (this helps
 				// when Win32 child windows are placed on the dialog
 				// when Win32 child windows are placed on the dialog
@@ -2441,8 +2458,23 @@ namespace DuiLib
 				POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
 				POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
 				m_ptLastMousePos = pt;
 				m_ptLastMousePos = pt;
 				CControlUI* pControl = FindControl(pt);
 				CControlUI* pControl = FindControl(pt);
-				if (pControl == NULL) break;
-				if (pControl->GetManager() != this) break;
+				if (pControl == NULL)
+				{
+					TouchTrace::Log(_T("LBUTTONDOWN no control hwnd=%p pt=%d,%d root=%p"),
+						(void*)m_hWndPaint, pt.x, pt.y, (void*)m_pRoot);
+					break;
+				}
+				if (pControl->GetManager() != this)
+				{
+					TouchTrace::Log(_T("LBUTTONDOWN foreign control hwnd=%p pt=%d,%d name=%s manager=%p self=%p"),
+						(void*)m_hWndPaint, pt.x, pt.y, pControl->GetName().GetData(),
+						(void*)pControl->GetManager(), (void*)this);
+					break;
+				}
+				TouchTrace::Log(_T("LBUTTONDOWN hit hwnd=%p name=%s class=%s pos=%d,%d,%d,%d enabled=%d visible=%d"),
+					(void*)m_hWndPaint, pControl->GetName().GetData(), pControl->GetClass(),
+					pControl->GetPos().left, pControl->GetPos().top, pControl->GetPos().right, pControl->GetPos().bottom,
+					(int)pControl->IsEnabled(), (int)pControl->IsVisible());
 
 
 				// 准备拖拽
 				// 准备拖拽
 				if (m_bDragDrop && pControl->IsDragEnabled())
 				if (m_bDragDrop && pControl->IsDragEnabled())
@@ -2506,8 +2538,11 @@ namespace DuiLib
 				const bool bPromotedTouchUp = IsPromotedTouchMouseMessage();
 				const bool bPromotedTouchUp = IsPromotedTouchMouseMessage();
 				// TOUCHUP 已经负责 tap/drag 判定;若提升的鼠标抬起先到,不能
 				// TOUCHUP 已经负责 tap/drag 判定;若提升的鼠标抬起先到,不能
 				// 绕过该判定触发 BUTTONUP。
 				// 绕过该判定触发 BUTTONUP。
-				if (m_pEventTouch != NULL)
+				if (m_pEventTouch != NULL || m_bSuppressPromotedTouchMouse)
+				{
+					m_bSuppressPromotedTouchMouse = false;
 					break;
 					break;
+				}
 				POINT ptButtonUp = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
 				POINT ptButtonUp = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
 				if (!bPromotedTouchUp)
 				if (!bPromotedTouchUp)
 				{
 				{
@@ -2536,6 +2571,8 @@ namespace DuiLib
 				m_bTouchMoved = false;  // 用完即清,绝不影响后续真实鼠标点击
 				m_bTouchMoved = false;  // 用完即清,绝不影响后续真实鼠标点击
 				if (pClick == NULL)
 				if (pClick == NULL)
 				{
 				{
+					TouchTrace::Log(_T("LBUTTONUP no click hwnd=%p pt=%d,%d"),
+						(void*)m_hWndPaint, pt.x, pt.y);
 					ReleaseCapture();
 					ReleaseCapture();
 					break;
 					break;
 				}
 				}

+ 1 - 0
DuiLib/Core/UIManager.h

@@ -527,6 +527,7 @@ namespace DuiLib {
 		POINT m_ptLastTouchPos = { 0, 0 };  // 上一包触点:用于去重 + 计算跟手滚动的位移增量
 		POINT m_ptLastTouchPos = { 0, 0 };  // 上一包触点:用于去重 + 计算跟手滚动的位移增量
 		POINT m_ptTouchStart = { 0, 0 };    // 本次手势起点:用于判断是否发生位移(拖拽 vs 轻点)
 		POINT m_ptTouchStart = { 0, 0 };    // 本次手势起点:用于判断是否发生位移(拖拽 vs 轻点)
 		bool m_bTouchMoved = false;         // 本次触摸是否发生位移(>阈值视为拖拽),松开时抑制点击
 		bool m_bTouchMoved = false;         // 本次触摸是否发生位移(>阈值视为拖拽),松开时抑制点击
+		bool m_bSuppressPromotedTouchMouse = false; // 触摸点击已由 TOUCHUP 处理,丢弃随后提升的鼠标点击
 		// 手指抬起后,Windows 仍会补发合成的 WM_MOUSEMOVE;且真实 WM_MOUSELEAVE 在
 		// 手指抬起后,Windows 仍会补发合成的 WM_MOUSEMOVE;且真实 WM_MOUSELEAVE 在
 		// m_bMouseTracking 为真时会【自己给自己重发 WM_MOUSEMOVE】(UIManager.cpp WM_MOUSELEAVE 分支),
 		// m_bMouseTracking 为真时会【自己给自己重发 WM_MOUSEMOVE】(UIManager.cpp WM_MOUSELEAVE 分支),
 		// 导致刚清掉的悬浮态立刻被重新点亮 → “悬浮态不消失 / 多个控件同时悬浮”。
 		// 导致刚清掉的悬浮态立刻被重新点亮 → “悬浮态不消失 / 多个控件同时悬浮”。