Browse Source

目前有个模态对话框可用版本,我先临时保存一下

张洋 3 weeks ago
parent
commit
49942a0848

+ 12 - 6
DuiLib/Core/UIBase.cpp

@@ -340,9 +340,12 @@ UINT CWindowWnd::ShowModal()
         (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);
-    // 临时诊断:禁用父窗口后立刻抓一次前台窗口,验证「禁用父窗口把前台从弹框抢走」假设
-    DuiLib::TouchTrace::Log(_T("MODAL-AFTER-DISABLE-PARENT hwnd=%p parent=%p foreground=%p active=%p focus=%p"),
+    ::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+    ::BringWindowToTop(m_hWnd);
+    ::SetForegroundWindow(m_hWnd);
+    ::SetActiveWindow(m_hWnd);
+    ::SetFocus(m_hWnd);
+    DuiLib::TouchTrace::Log(_T("MODAL-READY hwnd=%p parent=%p foreground=%p active=%p focus=%p"),
         (void*)m_hWnd, (void*)hWndParent, (void*)::GetForegroundWindow(), (void*)::GetActiveWindow(), (void*)::GetFocus());
     MSG msg = { 0 };
     while( ::IsWindow(m_hWnd) && ::GetMessage(&msg, NULL, 0, 0) ) {
@@ -354,11 +357,14 @@ UINT CWindowWnd::ShowModal()
             if( hFG != m_hWnd ) {
                 static HWND s_hForeign = NULL;
                 if( hFG != s_hForeign ) { s_hForeign = hFG; TouchTraceLogWindowIdentity(_T("FOREIGN-FG"), hFG); }
+                ::BringWindowToTop(m_hWnd);
+                ::SetForegroundWindow(m_hWnd);
+                ::SetActiveWindow(m_hWnd);
+                ::SetFocus(m_hWnd);
             }
         }
         if( msg.message == WM_CLOSE && msg.hwnd == m_hWnd ) {
             nRet = (int)msg.wParam;
-            ::EnableWindow(hWndParent, TRUE);
             ::SetFocus(hWndParent);
         }
         if( !CPaintManagerUI::TranslateMessage(&msg) ) {
@@ -373,8 +379,7 @@ UINT CWindowWnd::ShowModal()
         }
         if( msg.message == WM_QUIT ) break;
     }
-    ::EnableWindow(hWndParent, TRUE);
-    ::SetFocus(hWndParent);
+    if( hWndParent != NULL ) ::SetFocus(hWndParent);
     if( msg.message == WM_QUIT ) ::PostQuitMessage((int)msg.wParam);
     return nRet;
 }
@@ -403,6 +408,7 @@ void CWindowWnd::Close(UINT nRet)
 
     ASSERT(::IsWindow(m_hWnd));
     if (!::IsWindow(m_hWnd)) return;
+    CPaintManagerUI::BeginModalTouchMouseBarrier();
     PostMessage(WM_CLOSE, (WPARAM)nRet, 0L);
 }
 

+ 58 - 1
DuiLib/Core/UIManager.cpp

@@ -650,6 +650,8 @@ namespace DuiLib
 	namespace
 	{
 		const int kScrollBarTouchSlop = 12;   // 手指离滚动条 rect 的最大容差(像素)
+		DWORD s_dwModalTouchMouseBarrierUntil = 0;
+		bool s_bModalTouchMouseBarrierDownSeen = false;
 
 		// Windows 会把“触摸提升(promoted)出来的合成鼠标消息”打上 MOUSEEVENTF_FROMTOUCH 标记
 		// (位于 GetMessageExtraInfo() 的高位,MSDN 推荐判定值 0xFF515700)。
@@ -660,6 +662,41 @@ namespace DuiLib
 			return (::GetMessageExtraInfo() & 0xFFFFFF80) == 0xFF515700;
 		}
 
+		inline bool ConsumeModalTouchMouseBarrier(UINT uMsg)
+		{
+			if (s_dwModalTouchMouseBarrierUntil == 0)
+				return false;
+
+			if ((LONG)(::GetTickCount() - s_dwModalTouchMouseBarrierUntil) >= 0)
+			{
+				s_dwModalTouchMouseBarrierUntil = 0;
+				s_bModalTouchMouseBarrierDownSeen = false;
+				return false;
+			}
+
+			if (!IsPromotedTouchMouseMessage())
+				return false;
+
+			if (uMsg == WM_LBUTTONDOWN)
+			{
+				s_bModalTouchMouseBarrierDownSeen = true;
+				TouchTrace::Log(_T("MODAL-TOUCH-BARRIER consume DOWN"));
+				return true;
+			}
+
+			if (uMsg == WM_LBUTTONUP)
+			{
+				const bool bDownSeen = s_bModalTouchMouseBarrierDownSeen;
+				s_dwModalTouchMouseBarrierUntil = 0;
+				s_bModalTouchMouseBarrierDownSeen = false;
+				TouchTrace::Log(_T("MODAL-TOUCH-BARRIER consume UP and release downSeen=%d"),
+					(int)bDownSeen);
+				return true;
+			}
+
+			return false;
+		}
+
 		// 把触点收进滚动条自身 rect:垂直滚动条主要收敛 x(y 原样保留,纵向拖拽量完好)。
 		inline POINT Touch_SnapIntoScrollBar(const CControlUI* pBar, POINT pt)
 		{
@@ -730,6 +767,13 @@ namespace DuiLib
 		}
 	}
 
+	void CPaintManagerUI::BeginModalTouchMouseBarrier()
+	{
+		s_dwModalTouchMouseBarrierUntil = ::GetTickCount() + 250;
+		s_bModalTouchMouseBarrierDownSeen = false;
+		TouchTrace::Log(_T("MODAL-TOUCH-BARRIER armed until=%u"), s_dwModalTouchMouseBarrierUntil);
+	}
+
 	void CPaintManagerUI::InitTouchSupport()
 	{
 		if (m_hWndPaint == NULL || !::IsWindow(m_hWndPaint)) return;
@@ -763,6 +807,7 @@ namespace DuiLib
 		//      多个控件同时高亮”的根治手段;此处再叠加 m_bSuppressHoverAfterTouch 抑制抬起后的复活。
 		TouchApi::PFN_GetTouchInputInfo pfnGetInfo = TouchApi::GetGetTouchInputInfo();
 		if (pfnGetInfo == NULL) return;
+		bool bTouchInputClosed = false;
 
 		UINT cInputs = LOWORD(wParam);
 		TouchTrace::Log(_T("WM_TOUCH begin inputs=%u handle=%p"), cInputs, (HANDLE)lParam);
@@ -1006,6 +1051,15 @@ namespace DuiLib
 				{
 					CControlUI* pClick = m_pEventClick;
 					m_pEventClick = NULL;
+					m_pEventTouch = NULL;
+					m_pTouchScrollContainer = NULL;
+					m_bSuppressPromotedTouchMouse = true;
+					TouchApi::PFN_CloseTouchInputHandle pfnClose = TouchApi::GetCloseTouchInputHandle();
+					if (pfnClose != NULL)
+					{
+						pfnClose((HANDLE)lParam);
+						bTouchInputClosed = true;
+					}
 					TouchTrace::Log(_T("TOUCHUP click-candidate %s cls=%s pt=%d,%d"),
 						pClick->GetName().GetData(), pClick->GetClass(), pt.x, pt.y);
 					TEventUI clickEvent = { 0 };
@@ -1034,7 +1088,7 @@ namespace DuiLib
 		}
 
 		TouchApi::PFN_CloseTouchInputHandle pfnClose = TouchApi::GetCloseTouchInputHandle();
-		if (pfnClose != NULL)
+		if (!bTouchInputClosed && pfnClose != NULL)
 			pfnClose((HANDLE)lParam);
 	}
 
@@ -1665,6 +1719,9 @@ namespace DuiLib
 		// 无条件拦截会导致模态窗口完全无法触摸点击。
 		if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK)
 		{
+			if (ConsumeModalTouchMouseBarrier(uMsg))
+				return true;
+
 			if (m_pEventTouch != NULL || m_bSuppressPromotedTouchMouse)
 			{
 				if (uMsg == WM_LBUTTONUP || uMsg == WM_LBUTTONDBLCLK)

+ 1 - 0
DuiLib/Core/UIManager.h

@@ -484,6 +484,7 @@ namespace DuiLib {
 		void InitTouchSupport();
 		void OnTouchInput(WPARAM wParam, LPARAM lParam);
 		void ClearTouchHoverState(POINT pt);
+		static void BeginModalTouchMouseBarrier();
 
 	private:
 		CStdPtrArray* GetFoundControls();

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


+ 26 - 2
zhipuzi_pos_windows/page/CDiandanPageUI.cpp

@@ -855,8 +855,21 @@ void CDiandanPageUI::HandleClickMsg(TNotifyUI& msg)
 		CDiandanFoodItemUI* fooditemUI = static_cast<CDiandanFoodItemUI*>(msg.pSender);
 
 		m_cur_click_food_item = fooditemUI;
+		if (m_is_open_food_action_pending)
+		{
+			DuiLib::TouchTrace::Log(_T("FOOD-ACTION defer ignored: action already pending"));
+			return;
+		}
 
-		this->ClickFoodAction();
+		m_is_open_food_action_pending = true;
+		if (!::PostMessage(m_pMainWnd->GetHWND(), WM_DIANDAN_OPEN_FOOD_ACTION, 0, 0))
+		{
+			m_is_open_food_action_pending = false;
+			DuiLib::TouchTrace::Log(_T("FOOD-ACTION defer failed error=%u"), ::GetLastError());
+			return;
+		}
+		DuiLib::TouchTrace::Log(_T("FOOD-ACTION deferred hwnd=%p item=%s"),
+			(void*)m_pMainWnd->GetHWND(), fooditemUI->GetName().GetData());
 	}
 	else if (name == L"btn_diandan_jia")
 	{
@@ -1224,7 +1237,18 @@ void CDiandanPageUI::HandleTextCapture(std::string content)
 
 bool CDiandanPageUI::HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-	if (uMsg == WM_MYHOTKEY_WEIXIN_SHOUKUAN)
+	if (uMsg == WM_DIANDAN_OPEN_FOOD_ACTION)
+	{
+		m_is_open_food_action_pending = false;
+		DuiLib::TouchTrace::Log(_T("FOOD-ACTION deferred dispatch item=%s"),
+			m_cur_click_food_item != NULL ? m_cur_click_food_item->GetName().GetData() : _T("null"));
+		if (m_cur_click_food_item != NULL)
+		{
+			ClickFoodAction();
+		}
+		return true;
+	}
+	else if (uMsg == WM_MYHOTKEY_WEIXIN_SHOUKUAN)
 	{
 		StartWeixinzhifuShoukuan();
 

+ 2 - 1
zhipuzi_pos_windows/page/CDiandanPageUI.h

@@ -368,6 +368,7 @@ private:
 
 	//模态对话框有关的
 	bool m_is_show_modal_wnd = false;
+	bool m_is_open_food_action_pending = false;
 
 	//结算页面总的支付方式数量
 	int m_nZhiufuNum;
@@ -379,4 +380,4 @@ private:
 
 	//与称重显示相关的
 	bool m_is_dianzicheng_lianjie = false;
-};
+};

+ 2 - 0
zhipuzi_pos_windows/pch/define.h

@@ -5,6 +5,8 @@
 #define WM_SHOWTASK WM_APP + 1
 //关闭
 #define WM_ONCLOSE WM_APP + 2
+//点单商品点击后延迟打开属性框,避免在 WM_TOUCH 回调中嵌套进入模态消息循环
+#define WM_DIANDAN_OPEN_FOOD_ACTION WM_APP + 3
 
 //登录相关消息
 #define WM_LOGIN_ERROR WM_APP + 10001