释放鼠标捕获并让鼠标点击通过

2023-11-26

我有一个类似于弹出窗口或菜单的控件。我想显示它,当用户单击框的边界之外时,让它隐藏自己。我使用了 Mouse.Capture(this, CaptureMode.SubTree) 并以与 OnLostMouseCapture 中的 Menu/Popup 相同的方式重新获取了捕获。

当用户在控件边界外单击时,我在 OnPreviewMouseDown 中释放鼠标捕获。我没有将 e.Handled 设置为 true。鼠标单击将到达主 UI 上的其他控件,但不会到达窗口的关闭按钮(红色 X)。需要点击 2 次才能关闭应用程序。

有没有办法告诉 WPF 重新启动鼠标单击,或发送重复的鼠标单击事件?

这是我的代码。请注意,我将其重命名为 MainMenuControl - 我没有构建菜单,因此 Menu/MenuItem 和 Popup 不是选项。

public class MainMenuControl : Control
    {
        static MainMenuControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MainMenuControl), new FrameworkPropertyMetadata(typeof(MainMenuControl)));
        }

        public MainMenuControl()
        {
            this.Loaded += new RoutedEventHandler(MainMenuControl_Loaded);

            Mouse.AddPreviewMouseDownOutsideCapturedElementHandler(this, OnPreviewMouseDownOutsideCapturedElementHandler);
        }

        void MainMenuControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.IsVisibleChanged += new DependencyPropertyChangedEventHandler(MainMenuControl_IsVisibleChanged);
        }

        void MainMenuControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (this.IsVisible)
            {
                Mouse.Capture(this, CaptureMode.SubTree);
                Debug.WriteLine("Mouse.Capture");
            }
        }

        // I was doing this in OnPreviewMouseDown, but changing to this didn't have any effect
        private void OnPreviewMouseDownOutsideCapturedElementHandler(object sender, MouseButtonEventArgs e)
        {
            Debug.WriteLine("OnPreviewMouseDownOutsideCapturedElementHandler");

            if (!this.IsMouseInBounds())
            {
                if (Mouse.Captured == this)
                {
                    Mouse.Capture(this, CaptureMode.None);
                    Debug.WriteLine("Mouse.Capture released");
                }
                Debug.WriteLine("Close Menu");
            }
        }

        protected override void OnLostMouseCapture(MouseEventArgs e)
        {
            base.OnLostMouseCapture(e);

            Debug.WriteLine("OnLostMouseCapture");

            MainMenuControl reference = e.Source as MainMenuControl;
            if (Mouse.Captured != reference)
            {
                if (e.OriginalSource == reference)
                {
                    if ((Mouse.Captured == null) || (!reference.IsAncestorOf(Mouse.Captured as DependencyObject)))
                    {
                        //TODO: Close
                        Debug.WriteLine("Close Menu");
                    }
                }
                // if a child caused use to lose the capture, then recapture.
                else if (reference.IsAncestorOf(e.OriginalSource as DependencyObject))
                {
                    if (Mouse.Captured == null)
                    {
                        Mouse.Capture(reference, CaptureMode.SubTree);
                        Debug.WriteLine("Mouse.Capture");
                        e.Handled = true;
                    }
                }
                else
                {
                    //TODO: Close
                    Debug.WriteLine("Close Menu");
                }
            }

        }

        private bool IsMouseInBounds()
        {
            Point point = Mouse.GetPosition(this);
            Rect bounds = new Rect(0, 0, this.Width, this.Height);

            return bounds.Contains(point);
        }

    }

问题是您所讨论的鼠标处理位于 WPF 事件系统之外并且是操作系统的一部分,因此我们实际上讨论的是两个相当不同的鼠标消息队列,它们在大多数情况下都可以很好地交互,但在这些边缘情况下,我们可见互操作性并不完美。

您可以尝试生成 Win32 鼠标消息或向自己的窗口发送关闭消息,但所有这些方法都是 hack。由于弹出窗口和菜单表现出与您描述的完全相同的症状,因此似乎没有一种简单的方法可以实现您所描述的目标。

相反,我建议您考虑在鼠标离开窗口的北客户端区域或其他一些启发式(例如距控件的指定距离)时放弃鼠标捕获。我知道这可能并不理想,但如果您希望关闭按钮工作得足够糟糕,这可能是一个令人满意的折衷方案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

释放鼠标捕获并让鼠标点击通过 的相关文章

  • 如何在 WPF 中从原始帧渲染视频?

    我有一个特殊的摄像机 使用 GigEVision 协议 我使用提供的库进行控制 我可以订阅帧接收事件 然后通过 IntPtr 访问帧数据 在我的旧 WinForms 应用程序中 我可以通过从数据创建 Bitmap 对象并将其设置为 Pict
  • 我如何移动粘性/捕捉 wpf 窗口

    当我移动 主 窗口时 我想移动两个或更多粘性窗口 我想做这样的事情 private void MainWindow PreviewMouseMove object sender MouseEventArgs e if e LeftButto
  • 如何创建一个没有边框且只能通过手柄调整大小的 WPF 窗口?

    如果你设置ResizeMode CanResizeWithGrip 在 WPF 上Window然后右下角会出现一个调整大小的夹点 如下 如果你设置WindowStyle None 标题栏也会消失 但灰色斜边仍然保留 直到您设置ResizeM
  • wpf 的 prism 与 mvvm light

    我们正在启动一个带有 MVVM 的 WPF 项目 并且必须决定使用 PRISM 还是 MVVM Light 我对这两个框架都是新手 我已经阅读了一些帖子 但仍然有一些问题 有人可以阐明以下几个方面吗 两个框架 性能 无论出于何种原因 其中一
  • 如何在 WPF 应用程序中实现气球消息

    我们想使用气球消息 如UX Guide http msdn microsoft com en us library aa511451 aspx来自微软 我发现一些示例使用 Windows 窗体中的本机代码 但本机代码需要组件的句柄 这对于
  • 如何在 Oxyplot 中显示折线图的绘图点?

    这是我的图表的 xaml 代码
  • 创建面向鼠标和触摸的 WPF 应用程序的最佳实践[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 将集合绑定到自定义控件属性

    我没有运气尝试将数据集合绑定到我的自定义控件的属性 我已经实现了该控件的字符串属性的机制 在此处提供了一些帮助 并期望集合类型同样简单 但是我无法让它再次工作 这是我的自定义控件视图
  • 了解使用 Windows 本机 WPF 客户端进行 ADFS 登录

    我已经阅读了大量有关 ADFS 与 NodeJS Angular 或其他前端 Web 框架集成以及一般流程如何工作的文献 并通过 Auth0 Angular 起始代码构建了概念证明 但我不明白如何这可以与本机 WPF Windows 应用程
  • 带有命令绑定的 KeyBinding 不适用于 TextBox UpdateSourceTrigger LostFocus

    我正在使用 MVVM 并遇到以下问题 我的 TextBox Text 与 UpdateSourceTrigger LostFocus 绑定 这就是用户想要的 我有一个带有 SaveCommand CommandBinding 的按钮 这有效
  • 我的 WPF 应用程序中的 SaveFileDialog 异常

    我的一位客户在保存文件时遇到 WPF 应用程序崩溃的情况 我的保存文件代码是 var saveFileDialog new SaveFileDialog InitialDirectory string Concat Environment
  • 如何禁用列表框上的突出显示但保留选择?

    我无法找到如何不允许我的列表框突出显示所选项目 我知道我没有添加触发器来突出显示该项目
  • 如何更改 TextBox.Text 而不丢失 WPF 中的绑定?

    在 WPF 应用程序中 我正在创建一个设置窗口来自定义键盘快捷键 在文本框中 我处理 KeyDown 事件并将 Key 事件转换为人类可读的形式 以及我想要获取数据的形式 文本框声明如下
  • 如何从WPF中的另一个窗口调用方法

    我有两个窗户win1用于显示用户列表和其他win2用于添加用户 我还有一种在删除 更新或添加用户后刷新网格的方法 这个方法是在win1 我如何调用这个方法win2添加用户后 这是一个非常基本的面向对象设计问题 所以您希望能够从win2到一个
  • 在包含按钮的ListView中,如何获取单击按钮的索引?

    我有一个ListView仅包含按钮 我想做的很简单 我想要获得已单击按钮的索引 列表的计数从0到100不等 因此当用户单击按钮6时 我需要这个数字进行处理 我定义了我的ListView像这样
  • 增加 WPF 弹出动画的持续时间

    我有一个 WPF PopUp 控件 用于显示菜单叠加层 并且使用默认的淡入淡出动画 不过我想让动画需要更长的时间才能完成 我可以在 XAML 中做到这一点吗 你能在这里发布相关的xaml代码吗 否则 您可以查看这些链接以开始使用 xaml
  • 如何将 WPF 窗口置于前面?

    我创建了一个单实例应用程序 并且希望在用户多次启动该应用程序时激活已打开的窗口 这工作正常 但我有一个问题 如果已经打开的窗口超出了另一个应用程序窗口 我必须将其放在前面 我尝试过 window Focus 和 window Show 但它
  • WPF ListBox - 如何从数据表中放入值?

    I have ListBox并希望将值放入此列表框中DataTable listBoxVisibleFields DataContext SelectedFields Where SelectedFields is a DataTable充
  • 在哪里可以找到 WPF 应用程序中 UI 的一些主题/演示?

    我想使用 xaml 中的 Visual Studio Designer 设计一个现代外观的 UI 它为我提供了一个很好的工具箱 我可以使用它通过拖放来直观地创建 UI 由于它几乎表现得像 HTML 我想知道它是否也有丰富的主题库 我找到了一
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里

随机推荐