张洋 3 weeks ago
parent
commit
8513518351

+ 4 - 0
.github/copilot-instructions.md

@@ -0,0 +1,4 @@
+# Copilot Instructions
+
+## 项目指南
+- 用户明确要求:不要通过修改 WM_NCHITTEST/HTCAPTION 相关逻辑来解决触屏问题;因为鼠标点击完全正常,触屏问题应从触摸消息投递、WM_TOUCH/提升鼠标消息及模态消息循环方向定位。

+ 34 - 27
DuiLib/Core/UIBase.cpp

@@ -1,4 +1,9 @@
 #include "StdAfx.h"
 #include "StdAfx.h"
+#include "UIBase.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <tchar.h>
+#include <windows.h>
 
 
 #ifdef _DEBUG
 #ifdef _DEBUG
 #include <shlwapi.h>
 #include <shlwapi.h>
@@ -8,40 +13,24 @@
 namespace DuiLib {
 namespace DuiLib {
 
 
 namespace {
 namespace {
-    typedef BOOL (WINAPI* PFN_REGISTER_TOUCH_WINDOW)(HWND, ULONG);
+	typedef BOOL (WINAPI* PFN_REGISTER_TOUCH_WINDOW)(HWND, ULONG);
 
 
-    void RegisterTouchWindowIfAvailable(HWND hWnd)
-    {
-        if (hWnd == NULL) return;
-        HMODULE hUser32 = ::GetModuleHandle(_T("user32.dll"));
-        if (hUser32 == NULL) return;
-        PFN_REGISTER_TOUCH_WINDOW pfnRegister =
-            reinterpret_cast<PFN_REGISTER_TOUCH_WINDOW>(::GetProcAddress(hUser32, "RegisterTouchWindow"));
-        if (pfnRegister != NULL)
-            pfnRegister(hWnd, 0);
-    }
+	void RegisterTouchWindowIfAvailable(HWND hWnd)
+	{
+		if (hWnd == NULL) return;
+		HMODULE hUser32 = ::GetModuleHandle(_T("user32.dll"));
+		if (hUser32 == NULL) return;
+		PFN_REGISTER_TOUCH_WINDOW pfnRegister =
+			reinterpret_cast<PFN_REGISTER_TOUCH_WINDOW>(::GetProcAddress(hUser32, "RegisterTouchWindow"));
+		if (pfnRegister != NULL)
+			pfnRegister(hWnd, 0);
+	}
 }
 }
 
 
 /////////////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////////////
 //
 //
 //
 //
 
 
-void UILIB_API DUI__Trace(LPCTSTR pstrFormat, ...)
-{
-#ifdef _DEBUG
-	TCHAR szBuffer[2048] = {0};
-    va_list args;
-    va_start(args, pstrFormat);
-	_vsntprintf(szBuffer, 2048, pstrFormat, args); 
-    va_end(args);
-    
-	CDuiString strMsg = szBuffer;
-    strMsg += _T("\n");
-    OutputDebugString(strMsg.GetData());
-
-#endif
-}
-
 LPCTSTR DUI__TraceMsg(UINT uMsg)
 LPCTSTR DUI__TraceMsg(UINT uMsg)
 {
 {
 #define MSGDEF(x) if(uMsg==x) return _T(#x)
 #define MSGDEF(x) if(uMsg==x) return _T(#x)
@@ -328,18 +317,36 @@ UINT CWindowWnd::ShowModal()
     HWND hWndParent = GetWindowOwner(m_hWnd);
     HWND hWndParent = GetWindowOwner(m_hWnd);
     RegisterTouchWindowIfAvailable(m_hWnd);
     RegisterTouchWindowIfAvailable(m_hWnd);
     ::ShowWindow(m_hWnd, SW_SHOWNORMAL);
     ::ShowWindow(m_hWnd, SW_SHOWNORMAL);
+    ::SetForegroundWindow(m_hWnd);
+    ::SetActiveWindow(m_hWnd);
+    ::SetFocus(m_hWnd);
+    DuiLib::TouchTrace::Log(_T("MODAL-ENTER hwnd=%p owner=%p parent=%p foreground=%p active=%p focus=%p enabled=%d visible=%d style=0x%08X ex=0x%08X"),
+        (void*)m_hWnd, (void*)hWndParent, (void*)::GetParent(m_hWnd), (void*)::GetForegroundWindow(), (void*)::GetActiveWindow(), (void*)::GetFocus(),
+        (int)::IsWindowEnabled(m_hWnd), (int)::IsWindowVisible(m_hWnd),
+        (unsigned)::GetWindowLong(m_hWnd, GWL_STYLE), (unsigned)::GetWindowLong(m_hWnd, GWL_EXSTYLE));
     ::EnableWindow(hWndParent, FALSE);
     ::EnableWindow(hWndParent, FALSE);
     MSG msg = { 0 };
     MSG msg = { 0 };
     while( ::IsWindow(m_hWnd) && ::GetMessage(&msg, NULL, 0, 0) ) {
     while( ::IsWindow(m_hWnd) && ::GetMessage(&msg, NULL, 0, 0) ) {
+        if( msg.message == WM_TOUCH || msg.message == WM_LBUTTONDOWN || msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE ) {
+            DuiLib::TouchTrace::Log(_T("MODAL-RAW hwnd=%p msg=0x%04X target=%p w=0x%p l=0x%p capture=%p focus=%p active=%p foreground=%p"),
+                m_hWnd, msg.message, msg.hwnd, (void*)msg.wParam, (void*)msg.lParam,
+                (void*)::GetCapture(), (void*)::GetFocus(), (void*)::GetActiveWindow(), (void*)::GetForegroundWindow());
+        }
         if( msg.message == WM_CLOSE && msg.hwnd == m_hWnd ) {
         if( msg.message == WM_CLOSE && msg.hwnd == m_hWnd ) {
             nRet = (int)msg.wParam;
             nRet = (int)msg.wParam;
             ::EnableWindow(hWndParent, TRUE);
             ::EnableWindow(hWndParent, TRUE);
             ::SetFocus(hWndParent);
             ::SetFocus(hWndParent);
         }
         }
         if( !CPaintManagerUI::TranslateMessage(&msg) ) {
         if( !CPaintManagerUI::TranslateMessage(&msg) ) {
+            if( msg.message == WM_TOUCH || msg.message == WM_LBUTTONDOWN || msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE ) {
+                DuiLib::TouchTrace::Log(_T("MODAL-LOOP dispatch hwnd=%p msg=0x%04X target=%p"), m_hWnd, msg.message, msg.hwnd);
+            }
             ::TranslateMessage(&msg);
             ::TranslateMessage(&msg);
             ::DispatchMessage(&msg);
             ::DispatchMessage(&msg);
         }
         }
+        else if( msg.message == WM_TOUCH || msg.message == WM_LBUTTONDOWN || msg.message == WM_LBUTTONUP || msg.message == WM_MOUSEMOVE ) {
+            DuiLib::TouchTrace::Log(_T("MODAL-LOOP consumed hwnd=%p msg=0x%04X target=%p"), m_hWnd, msg.message, msg.hwnd);
+        }
         if( msg.message == WM_QUIT ) break;
         if( msg.message == WM_QUIT ) break;
     }
     }
     ::EnableWindow(hWndParent, TRUE);
     ::EnableWindow(hWndParent, TRUE);

+ 4 - 1
DuiLib/Core/UIBase.h

@@ -40,7 +40,10 @@ namespace DuiLib {
 #define DUITRACEMSG _T("")
 #define DUITRACEMSG _T("")
 #endif
 #endif
 
 
-	void UILIB_API DUI__Trace(LPCTSTR pstrFormat, ...);
+	namespace TouchTrace
+	{
+		UILIB_API void Log(LPCTSTR pstrFormat, ...);
+	}
 	LPCTSTR UILIB_API DUI__TraceMsg(UINT uMsg);
 	LPCTSTR UILIB_API DUI__TraceMsg(UINT uMsg);
 
 
 	/////////////////////////////////////////////////////////////////////////////////////
 	/////////////////////////////////////////////////////////////////////////////////////

+ 89 - 3
DuiLib/Core/UIManager.cpp

@@ -1,4 +1,5 @@
 #include "StdAfx.h"
 #include "StdAfx.h"
+#include <windows.h>
 #include <zmouse.h>
 #include <zmouse.h>
 // [触屏诊断] 显式引入,避免依赖 tchar.h 的传递包含
 // [触屏诊断] 显式引入,避免依赖 tchar.h 的传递包含
 #include <stdio.h>
 #include <stdio.h>
@@ -992,9 +993,11 @@ namespace DuiLib
 					? Touch_SnapIntoScrollBar(m_pEventTouch, pt) : pt;
 					? Touch_SnapIntoScrollBar(m_pEventTouch, pt) : pt;
 				event.dwTimestamp = ::GetTickCount();
 				event.dwTimestamp = ::GetTickCount();
 				event.wKeyState = MapKeyState();
 				event.wKeyState = MapKeyState();
-				TouchTrace::Log(_T("TOUCHUP touch=%s moved=%d hover=%p leaveArr=%d click=%p capture=%d"),
+				TouchTrace::Log(_T("TOUCHUP touch=%s moved=%d hover=%p leaveArr=%d click=%p capture=%d clickName=%s clickCls=%s"),
 					m_pEventTouch->GetName().GetData(), (int)m_bTouchMoved, (void*)m_pEventHover,
 					m_pEventTouch->GetName().GetData(), (int)m_bTouchMoved, (void*)m_pEventHover,
-					m_aNeedMouseLeaveNeeded.GetSize(), (void*)m_pEventClick, (int)m_bMouseCapture);
+					m_aNeedMouseLeaveNeeded.GetSize(), (void*)m_pEventClick, (int)m_bMouseCapture,
+					m_pEventClick != NULL ? m_pEventClick->GetName().GetData() : _T("null"),
+					m_pEventClick != NULL ? m_pEventClick->GetClass() : _T("null"));
 				m_pEventTouch->Event(event);
 				m_pEventTouch->Event(event);
 
 
 				if (m_pEventClick != NULL && !m_bTouchMoved
 				if (m_pEventClick != NULL && !m_bTouchMoved
@@ -1002,6 +1005,8 @@ namespace DuiLib
 				{
 				{
 					CControlUI* pClick = m_pEventClick;
 					CControlUI* pClick = m_pEventClick;
 					m_pEventClick = NULL;
 					m_pEventClick = NULL;
+					TouchTrace::Log(_T("TOUCHUP click-candidate %s cls=%s pt=%d,%d"),
+						pClick->GetName().GetData(), pClick->GetClass(), pt.x, pt.y);
 					TEventUI clickEvent = { 0 };
 					TEventUI clickEvent = { 0 };
 					clickEvent.Type = UIEVENT_BUTTONDOWN;
 					clickEvent.Type = UIEVENT_BUTTONDOWN;
 					clickEvent.pSender = pClick;
 					clickEvent.pSender = pClick;
@@ -1015,6 +1020,8 @@ namespace DuiLib
 				}
 				}
 				else if (m_pEventClick != NULL)
 				else if (m_pEventClick != NULL)
 				{
 				{
+					TouchTrace::Log(_T("TOUCHUP drop-candidate %s cls=%s moved=%d"),
+						m_pEventClick->GetName().GetData(), m_pEventClick->GetClass(), (int)m_bTouchMoved);
 					// 拖动或滚动条触摸从未发送 BUTTONDOWN,直接丢弃候选点击。
 					// 拖动或滚动条触摸从未发送 BUTTONDOWN,直接丢弃候选点击。
 					m_pEventClick = NULL;
 					m_pEventClick = NULL;
 				}
 				}
@@ -1562,12 +1569,22 @@ namespace DuiLib
 
 
 	bool CPaintManagerUI::PreMessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)
 	bool CPaintManagerUI::PreMessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes)
 	{
 	{
+		if (uMsg == WM_TOUCH || uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_MOUSEMOVE)
+		{
+			TouchTrace::Log(_T("PRE-HANDLER enter hwnd=%p manager=%p msg=0x%04X w=0x%p l=0x%p"),
+				(void*)m_hWndPaint, (void*)this, uMsg, (void*)wParam, (void*)lParam);
+		}
 		for (int i = 0; i < m_aPreMessageFilters.GetSize(); i++)
 		for (int i = 0; i < m_aPreMessageFilters.GetSize(); i++)
 		{
 		{
 			bool bHandled = false;
 			bool bHandled = false;
 			LRESULT lResult = static_cast<IMessageFilterUI*>(m_aPreMessageFilters[i])->MessageHandler(uMsg, wParam, lParam, bHandled);
 			LRESULT lResult = static_cast<IMessageFilterUI*>(m_aPreMessageFilters[i])->MessageHandler(uMsg, wParam, lParam, bHandled);
 			if (bHandled)
 			if (bHandled)
 			{
 			{
+				if (uMsg == WM_TOUCH || uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_MOUSEMOVE)
+				{
+					TouchTrace::Log(_T("PRE-HANDLER filter-consumed hwnd=%p manager=%p filter=%p msg=0x%04X res=0x%p"),
+						(void*)m_hWndPaint, (void*)this, (void*)m_aPreMessageFilters[i], uMsg, (void*)lResult);
+				}
 				lRes = lResult;
 				lRes = lResult;
 				return true;
 				return true;
 			}
 			}
@@ -1627,6 +1644,12 @@ 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 || uMsg == WM_MOUSEMOVE)
+		{
+			TouchTrace::Log(_T("MSG-HANDLER enter 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);
+		}
 		if (uMsg == WM_TOUCH || uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
 		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"),
 			TouchTrace::Log(_T("MANAGER-MSG hwnd=%p manager=%p msg=0x%04X w=0x%p l=0x%p touch=%p suppress=%d"),
@@ -1662,6 +1685,11 @@ namespace DuiLib
 			LRESULT lResult = static_cast<IMessageFilterUI*>(m_aMessageFilters[i])->MessageHandler(uMsg, wParam, lParam, bHandled);
 			LRESULT lResult = static_cast<IMessageFilterUI*>(m_aMessageFilters[i])->MessageHandler(uMsg, wParam, lParam, bHandled);
 			if (bHandled)
 			if (bHandled)
 			{
 			{
+				if (uMsg == WM_TOUCH || uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_MOUSEMOVE)
+				{
+					TouchTrace::Log(_T("MSG-HANDLER filter-consumed hwnd=%p manager=%p filter=%p msg=0x%04X res=0x%p"),
+						(void*)m_hWndPaint, (void*)this, (void*)m_aMessageFilters[i], uMsg, (void*)lResult);
+				}
 				lRes = lResult;
 				lRes = lResult;
 				switch (uMsg)
 				switch (uMsg)
 				{
 				{
@@ -2448,7 +2476,12 @@ namespace DuiLib
 				// WM_TOUCH 后 Windows 可能补发 WM_LBUTTONDOWN。触摸点击由 TOUCHUP
 				// WM_TOUCH 后 Windows 可能补发 WM_LBUTTONDOWN。触摸点击由 TOUCHUP
 				// 的 tap 判定统一处理,不能让这条合成消息提前建立鼠标点击状态。
 				// 的 tap 判定统一处理,不能让这条合成消息提前建立鼠标点击状态。
 				if (m_pEventTouch != NULL || m_bSuppressPromotedTouchMouse)
 				if (m_pEventTouch != NULL || m_bSuppressPromotedTouchMouse)
+				{
+					TouchTrace::Log(_T("LBUTTONDOWN swallowed by touch-state touch=%s suppress=%d"),
+						m_pEventTouch != NULL ? m_pEventTouch->GetName().GetData() : _T("null"),
+						(int)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
 				// and we need to remove them on focus change).
 				// and we need to remove them on focus change).
@@ -2540,6 +2573,9 @@ namespace DuiLib
 				// 绕过该判定触发 BUTTONUP。
 				// 绕过该判定触发 BUTTONUP。
 				if (m_pEventTouch != NULL || m_bSuppressPromotedTouchMouse)
 				if (m_pEventTouch != NULL || m_bSuppressPromotedTouchMouse)
 				{
 				{
+					TouchTrace::Log(_T("LBUTTONUP swallowed by touch-state touch=%s suppress=%d"),
+						m_pEventTouch != NULL ? m_pEventTouch->GetName().GetData() : _T("null"),
+						(int)m_bSuppressPromotedTouchMouse);
 					m_bSuppressPromotedTouchMouse = false;
 					m_bSuppressPromotedTouchMouse = false;
 					break;
 					break;
 				}
 				}
@@ -4954,6 +4990,7 @@ namespace DuiLib
 		UINT uStyle = GetWindowStyle(pMsg->hwnd);
 		UINT uStyle = GetWindowStyle(pMsg->hwnd);
 		UINT uChildRes = uStyle & WS_CHILD;
 		UINT uChildRes = uStyle & WS_CHILD;
 		LRESULT lRes = 0;
 		LRESULT lRes = 0;
+		const bool bTraceTouch = (pMsg->message == WM_TOUCH || pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONUP || pMsg->message == WM_MOUSEMOVE);
 		if (uChildRes != 0)
 		if (uChildRes != 0)
 		{
 		{
 			HWND hWndParent = ::GetParent(pMsg->hwnd);
 			HWND hWndParent = ::GetParent(pMsg->hwnd);
@@ -4966,10 +5003,30 @@ namespace DuiLib
 				{
 				{
 					if (pMsg->hwnd == pT->GetPaintWindow() || hTempParent == pT->GetPaintWindow())
 					if (pMsg->hwnd == pT->GetPaintWindow() || hTempParent == pT->GetPaintWindow())
 					{
 					{
+						if (bTraceTouch)
+						{
+							TouchTrace::Log(_T("TRANSLATE match(child) msg=0x%04X src=%p target=%p parent=%p"),
+								pMsg->message, (void*)pMsg->hwnd, (void*)pT->GetPaintWindow(), (void*)hTempParent);
+						}
 						if (pT->TranslateAccelerator(pMsg))
 						if (pT->TranslateAccelerator(pMsg))
+						{
+							if (bTraceTouch)
+							{
+								TouchTrace::Log(_T("TRANSLATE accel-consumed(child) msg=0x%04X target=%p"),
+									pMsg->message, (void*)pT->GetPaintWindow());
+							}
 							return true;
 							return true;
+						}
 
 
-						pT->PreMessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, lRes);
+						if (pT->PreMessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, lRes))
+						{
+							if (bTraceTouch)
+							{
+								TouchTrace::Log(_T("TRANSLATE pre-consumed(child) msg=0x%04X target=%p res=0x%p"),
+									pMsg->message, (void*)pT->GetPaintWindow(), (void*)lRes);
+							}
+							return true;
+						}
 					}
 					}
 					hTempParent = GetParent(hTempParent);
 					hTempParent = GetParent(hTempParent);
 				}
 				}
@@ -4982,16 +5039,45 @@ namespace DuiLib
 				CPaintManagerUI* pT = static_cast<CPaintManagerUI*>(m_aPreMessages[i]);
 				CPaintManagerUI* pT = static_cast<CPaintManagerUI*>(m_aPreMessages[i]);
 				if (pMsg->hwnd == pT->GetPaintWindow())
 				if (pMsg->hwnd == pT->GetPaintWindow())
 				{
 				{
+					if (bTraceTouch)
+					{
+						TouchTrace::Log(_T("TRANSLATE match(top) msg=0x%04X src=%p target=%p"),
+							pMsg->message, (void*)pMsg->hwnd, (void*)pT->GetPaintWindow());
+					}
 					if (pT->TranslateAccelerator(pMsg))
 					if (pT->TranslateAccelerator(pMsg))
+					{
+						if (bTraceTouch)
+						{
+							TouchTrace::Log(_T("TRANSLATE accel-consumed(top) msg=0x%04X target=%p"),
+								pMsg->message, (void*)pT->GetPaintWindow());
+						}
 						return true;
 						return true;
+					}
 
 
 					if (pT->PreMessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, lRes))
 					if (pT->PreMessageHandler(pMsg->message, pMsg->wParam, pMsg->lParam, lRes))
+					{
+						if (bTraceTouch)
+						{
+							TouchTrace::Log(_T("TRANSLATE pre-consumed(top) msg=0x%04X target=%p res=0x%p"),
+								pMsg->message, (void*)pT->GetPaintWindow(), (void*)lRes);
+						}
 						return true;
 						return true;
+					}
 
 
+					if (bTraceTouch)
+					{
+						TouchTrace::Log(_T("TRANSLATE no-consume(top) msg=0x%04X target=%p"),
+							pMsg->message, (void*)pT->GetPaintWindow());
+					}
 					return false;
 					return false;
 				}
 				}
 			}
 			}
 		}
 		}
+		if (bTraceTouch)
+		{
+			TouchTrace::Log(_T("TRANSLATE no-match msg=0x%04X src=%p child=%u"),
+				pMsg->message, (void*)pMsg->hwnd, (unsigned)uChildRes);
+		}
 		return false;
 		return false;
 	}
 	}
 
 

BIN
bin/Win32/Release/zhipuzi_pos_windows/DuiLib.dll


BIN
bin/Win32/Release/zhipuzi_pos_windows/zhipuzi_pos_windows.exe


BIN
dll/release/DuiLib.dll


BIN
lib/release/DuiLib.lib


BIN
pdb/release/DuiLib.pdb