diff --git a/Ink Canvas/Helpers/FloatingWindowInterceptor.cs b/Ink Canvas/Helpers/FloatingWindowInterceptor.cs index d94004cb..1a411319 100644 --- a/Ink Canvas/Helpers/FloatingWindowInterceptor.cs +++ b/Ink Canvas/Helpers/FloatingWindowInterceptor.cs @@ -822,10 +822,6 @@ namespace Ink_Canvas.Helpers var foundWindows = new List<(IntPtr hwnd, InterceptRule rule)>(); - // Reset per-scan state - foreach (var rule in _interceptRules.Values) - rule.foundHwnd = false; - EnumWindows((hWnd, lParam) => { EnumChildWindows(hWnd, (childHwnd, _) => @@ -840,13 +836,11 @@ namespace Ink_Canvas.Helpers var interceptedCount = 0; foreach (var (hWnd, rule) in foundWindows) { - bool shouldAct = !_interceptedWindows.ContainsKey(hWnd) || - (_interceptedWindows.ContainsKey(hWnd) && IsWindowVisible(hWnd)); - if (shouldAct) - { - ApplyIntercept(hWnd, rule); - interceptedCount++; - } + // 已被隐藏且仍不可见:已拦截,无需重复操作 + if (_interceptedWindows.ContainsKey(hWnd) && !IsWindowVisible(hWnd)) + continue; + ApplyIntercept(hWnd, rule); + interceptedCount++; } if (interceptedCount == 0) _consecutiveEmptyScans++; @@ -865,19 +859,21 @@ namespace Ink_Canvas.Helpers private void CheckWindow(IntPtr hWnd, List<(IntPtr, InterceptRule)> found) { - if (!IsWindow(hWnd) || !IsWindowVisible(hWnd)) return; + // 必须是合法窗口句柄,但不要求可见(被我们隐藏的窗口也需要被发现以维持拦截状态) + if (!IsWindow(hWnd)) return; foreach (var rule in _interceptRules.Values) { - if (!rule.IsEnabled || rule.foundHwnd) continue; + if (!rule.IsEnabled) continue; if (MatchesRule(hWnd, rule)) { - rule.outHwnd = hWnd; - rule.foundHwnd = true; found.Add((hWnd, rule)); + break; // 一个窗口只匹配第一条命中的规则 } } } +<<>> +END_CALL private bool MatchesRule(IntPtr hWnd, InterceptRule rule) { @@ -954,34 +950,36 @@ namespace Ink_Canvas.Helpers int h = rect.Bottom - rect.Top; if (w == 0 && h == 0) return false; + // DWM 返回物理像素,GetSystemMetrics 返回逻辑像素,需换算 + var hdc = GetDC(IntPtr.Zero); + float scaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; + float scaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f; + ReleaseDC(IntPtr.Zero, hdc); + int screenW = (int)(GetSystemMetrics(SM_CXSCREEN) * scaleX); + int screenH = (int)(GetSystemMetrics(SM_CYSCREEN) * scaleY); + const int tolerance = 2; switch (rule.SizeMatchType) { case SizeMatchType.FullScreen: - if (w != GetSystemMetrics(SM_CXSCREEN) || h != GetSystemMetrics(SM_CYSCREEN)) + if (Math.Abs(w - screenW) > tolerance || Math.Abs(h - screenH) > tolerance) return false; break; case SizeMatchType.FullHeight: - if (h != GetSystemMetrics(SM_CYSCREEN)) return false; + if (Math.Abs(h - screenH) > tolerance) return false; break; case SizeMatchType.FullWidth: - if (w != GetSystemMetrics(SM_CXSCREEN)) return false; + if (Math.Abs(w - screenW) > tolerance) return false; break; case SizeMatchType.Exact: if (w != rule.WindowWidth || h != rule.WindowHeight) return false; break; case SizeMatchType.DPIScale: - { - var hdc = GetDC(IntPtr.Zero); - float scaleX = GetDeviceCaps(hdc, LOGPIXELSX) / 96.0f; - float scaleY = GetDeviceCaps(hdc, LOGPIXELSY) / 96.0f; - ReleaseDC(IntPtr.Zero, hdc); if (Math.Abs(rule.WindowWidth * scaleX - w) > tolerance || Math.Abs(rule.WindowHeight * scaleY - h) > tolerance) return false; break; - } case SizeMatchType.Scale: { if (rule.WindowWidth == 0 || rule.WindowHeight == 0) return false;