Browse Source

修复鼠标移到标题栏悬浮态的问题

张洋 3 weeks ago
parent
commit
2924a08507

+ 54 - 0
DuiLib/Core/UIManager.cpp

@@ -4685,6 +4685,36 @@ namespace DuiLib
 				}
 			}
 			return true;
+			case WM_NCMOUSEMOVE:
+			{
+				// ------------------------------------------------------------
+				// [第 48 轮] 鼠标一进入**非客户区**(标题栏 caption / 边框),
+				//   客户区就再也收不到 WM_MOUSEMOVE 了。而悬浮态的 enter/leave
+				//   **只在 WM_MOUSEMOVE 里切换**(见下面 4904 那段的总闸)
+				//   ⇒ 移进标题栏之前点亮的那颗控件会一直保持悬浮态。
+				//
+				//   为什么标题栏属于非客户区:本项目的自绘标题栏靠
+				//   `CMainWnd::OnNcHitTest` / `CChufangSettingWnd::OnNcHitTest`
+				//   返回 HTCAPTION 实现拖动 —— 判据是"落在 caption 矩形内、
+				//   且命中控件的 class 不是 ButtonUI/OptionUI/TextUI"。
+				//   所以**标题栏空白区 = HTCAPTION = 非客户区**(用户复现的正是
+				//   从「+」按钮往右上移到标题栏空白处);标题栏上的按钮仍是
+				//   HTCLIENT,走正常客户区消息,不受本分支影响。
+				//
+				//   判据是纯状态的 `wParam`(HTCAPTION / HTLEFT / HTTOP / …):
+				//   能进本 case,就已经不在客户区了,**不需要任何时间戳**。
+				//
+				//   ⚠️ 必须 `return false`:这里只是在旁边补一个副作用,
+				//      消息本身必须继续落到 DefWindowProc —— 拖动窗口、
+				//      边框改尺寸全靠它,拦掉就再也拖不动窗口了。
+				// ------------------------------------------------------------
+				if (m_pEventHover != NULL || m_aNeedMouseLeaveNeeded.GetSize() > 0)
+				{
+					POINT ptNoTarget = { -1, -1 };
+					ClearTouchHoverState(ptNoTarget);
+				}
+			}
+			return false;
 			case WM_MOUSELEAVE:
 			{
 				if (m_hwndTooltip != NULL) ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM)&m_ToolTip);
@@ -4758,8 +4788,32 @@ namespace DuiLib
 					// 明显移动 ⇒ 抑制期结束,落到下面走正常的鼠标移动流程。
 				}
 
+				// ------------------------------------------------------------
+				// [第 48 轮] `lParam == -1` 是"**客户区已无悬浮目标**"的哨兵。
+				//
+				//   全库产生它的地方**只有一处**:上面 WM_MOUSELEAVE 分支——
+				//   鼠标离开客户区时(移进标题栏 caption、或整体移出窗口),
+				//   系统只给一次 WM_MOUSELEAVE,那条分支就回发本哨兵。
+				//
+				//   原写法是 `break;`(1aacbb0d0 / 09-19 加)。那等于把 nim 原版
+				//   "让 FindControl((-1,-1)) 落空 ⇒ 对 m_pEventHover 补发
+				//   MOUSELEAVE"的收尾通道**整条掐断** ⇒ 鼠标从按钮移进标题栏
+				//   之后,该控件的悬浮态永不消失(主窗口与所有弹框一致复现)。
+				//
+				//   现在:哨兵仍然 break(绝不参与下面的坐标/拖拽/抑制判据——
+				//   m_ptLastMousePos 与 s_ptLastTouchScreen 都不能被 (-1,-1)
+				//   污染,否则 bNeedDrag 会误判、触摸后的悬浮抑制也会被提前解除),
+				//   但**先把该做的收尾做掉**。
+				// ------------------------------------------------------------
 				if ((INT_PTR)lParam == -1)
+				{
+					if (m_pEventHover != NULL || m_aNeedMouseLeaveNeeded.GetSize() > 0)
+					{
+						POINT ptNoTarget = { -1, -1 };
+						ClearTouchHoverState(ptNoTarget);
+					}
 					break;
+				}
 
 				POINT ptCheck = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
 				if (s_bSuppressHoverAfterTouch)

BIN
bin/Win32/Debug/zhipuzi_pos_windows/DuiLib_d.dll


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


BIN
dll/debug/DuiLib_d.dll


BIN
dll/release/DuiLib.dll


BIN
pdb/release/DuiLib.pdb