A:解决菜单弹出无法关闭的问题
This commit is contained in:
1 parent
5a4f8ebc24
commit
4f4a3b70c5
3 files changed
+84
-18
No files matched your search
@@ -80,7 +80,7 @@ public static class SysInfoUtils
|
|||||||
}
|
}
|
||||||
catch (ArgumentException)
|
catch (ArgumentException)
|
||||||
{
|
{
|
||||||
Log.Information($"进程 {pid} 不存在");
|
// Log.Information($"进程 {pid} 不存在");
|
||||||
return null; // 返回 null 而不是抛异常
|
return null; // 返回 null 而不是抛异常
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -473,6 +473,7 @@ public partial class App : System.Windows.Application
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Console.WriteLine(context.RequestBody);
|
||||||
if (string.IsNullOrEmpty(context.RequestBody))
|
if (string.IsNullOrEmpty(context.RequestBody))
|
||||||
{
|
{
|
||||||
context.Response.StatusCode = 400;
|
context.Response.StatusCode = 400;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class TrayIconManager : IDisposable
|
|||||||
private ContextMenu _contextMenu;
|
private ContextMenu _contextMenu;
|
||||||
private DispatcherTimer _clickTimer;
|
private DispatcherTimer _clickTimer;
|
||||||
private bool _isDoubleClick = false;
|
private bool _isDoubleClick = false;
|
||||||
|
private DispatcherTimer _menuCloseTimer;
|
||||||
|
|
||||||
// Win32 API 用于获取鼠标位置和显示器信息
|
// Win32 API 用于获取鼠标位置和显示器信息
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
@@ -264,30 +265,93 @@ public class TrayIconManager : IDisposable
|
|||||||
// 更新菜单状态
|
// 更新菜单状态
|
||||||
UpdateContextMenuStates();
|
UpdateContextMenuStates();
|
||||||
|
|
||||||
// 直接设置菜单位置为鼠标位置,不使用临时窗口
|
// 简单设置菜单位置
|
||||||
_contextMenu.PlacementTarget = null;
|
_contextMenu.PlacementTarget = null;
|
||||||
_contextMenu.Placement = PlacementMode.MousePoint;
|
_contextMenu.Placement = PlacementMode.MousePoint;
|
||||||
_contextMenu.StaysOpen = false;
|
_contextMenu.StaysOpen = true; // 保持打开,我们手动控制关闭
|
||||||
|
|
||||||
// 使用 PreviewMouseDown 事件来处理点击外部关闭
|
|
||||||
_contextMenu.PreviewMouseDown += OnContextMenuPreviewMouseDown;
|
|
||||||
|
|
||||||
// 当菜单关闭时,清理事件
|
|
||||||
RoutedEventHandler closedHandler = null;
|
|
||||||
closedHandler = (s, e) =>
|
|
||||||
{
|
|
||||||
_contextMenu.PreviewMouseDown -= OnContextMenuPreviewMouseDown;
|
|
||||||
_contextMenu.Closed -= closedHandler;
|
|
||||||
};
|
|
||||||
_contextMenu.Closed += closedHandler;
|
|
||||||
|
|
||||||
_contextMenu.IsOpen = true;
|
_contextMenu.IsOpen = true;
|
||||||
|
|
||||||
|
// 启动定时器来检测点击外部
|
||||||
|
StartMenuCloseTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnContextMenuPreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
private void StartMenuCloseTimer()
|
||||||
{
|
{
|
||||||
// 如果点击的是菜单项,让事件继续处理
|
if (_menuCloseTimer != null)
|
||||||
// 这个方法主要是为了确保菜单行为正常
|
{
|
||||||
|
_menuCloseTimer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
_menuCloseTimer = new DispatcherTimer
|
||||||
|
{
|
||||||
|
Interval = TimeSpan.FromMilliseconds(100) // 每100ms检查一次
|
||||||
|
};
|
||||||
|
|
||||||
|
_menuCloseTimer.Tick += (s, e) =>
|
||||||
|
{
|
||||||
|
if (!_contextMenu.IsOpen)
|
||||||
|
{
|
||||||
|
_menuCloseTimer.Stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查ESC键是否被按下
|
||||||
|
if (System.Windows.Input.Keyboard.IsKeyDown(System.Windows.Input.Key.Escape))
|
||||||
|
{
|
||||||
|
_contextMenu.IsOpen = false;
|
||||||
|
_menuCloseTimer.Stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否有鼠标按键按下
|
||||||
|
if (System.Windows.Input.Mouse.LeftButton == System.Windows.Input.MouseButtonState.Pressed ||
|
||||||
|
System.Windows.Input.Mouse.RightButton == System.Windows.Input.MouseButtonState.Pressed)
|
||||||
|
{
|
||||||
|
// 如果鼠标不在菜单区域内且有按键按下,则关闭菜单
|
||||||
|
if (!IsMouseOverContextMenu())
|
||||||
|
{
|
||||||
|
_contextMenu.IsOpen = false;
|
||||||
|
_menuCloseTimer.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
_menuCloseTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsMouseOverContextMenu()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_contextMenu.IsOpen) return false;
|
||||||
|
|
||||||
|
// 获取屏幕上的鼠标位置
|
||||||
|
GetCursorPos(out POINT screenPoint);
|
||||||
|
var screenPosition = new System.Windows.Point(screenPoint.X, screenPoint.Y);
|
||||||
|
|
||||||
|
// 获取菜单的屏幕位置和大小
|
||||||
|
var contextMenuElement = _contextMenu as FrameworkElement;
|
||||||
|
if (contextMenuElement == null) return false;
|
||||||
|
|
||||||
|
var source = PresentationSource.FromVisual(contextMenuElement);
|
||||||
|
if (source == null) return false;
|
||||||
|
|
||||||
|
// 获取菜单的屏幕边界
|
||||||
|
var menuTopLeft = contextMenuElement.PointToScreen(new System.Windows.Point(0, 0));
|
||||||
|
var menuBottomRight =
|
||||||
|
contextMenuElement.PointToScreen(new System.Windows.Point(contextMenuElement.ActualWidth,
|
||||||
|
contextMenuElement.ActualHeight));
|
||||||
|
|
||||||
|
var menuBounds = new Rect(menuTopLeft, menuBottomRight);
|
||||||
|
|
||||||
|
return menuBounds.Contains(screenPosition);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 如果检测失败,假设鼠标不在菜单上,这样会更安全
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateContextMenuStates()
|
private void UpdateContextMenuStates()
|
||||||
@@ -446,5 +510,6 @@ public class TrayIconManager : IDisposable
|
|||||||
_notifyIcon?.Dispose();
|
_notifyIcon?.Dispose();
|
||||||
_contextMenu = null;
|
_contextMenu = null;
|
||||||
_clickTimer?.Stop();
|
_clickTimer?.Stop();
|
||||||
|
_menuCloseTimer?.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user