.net - 我们可以更改 Windows 中的事件路由策略吗?

标签 .net winforms window

在 .NET 窗口窗体中,窗体具有控件集合,并且在内部所有控件都只是环绕 Microsoft Windows 提供的窗口子系统。有点类似于 MFC,它是窗口 api 的浅层包装器。表单/窗口中的控件创建树结构,叶节点接收事件,例如MouseMove 事件将由鼠标正下方的窗口/控件接收。

但是在微软提供的展示框架中RoutedEvent它可以有以下策略之一

  1. 隧道 路由事件使用隧道策略,其中事件实例通过树向下路由,从根元素到源元素。
  2. 冒泡 路由事件使用冒泡策略,其中事件实例通过树向上路由,从事件源到根。
  3. 直接 路由事件不通过元素树路由。

我的猜测是表示框架只创建一个主窗口并自行绘制子元素以支持事件路由策略

现在我可以在我的正常窗口窗体中更改此策略。我想要TunnelBubble 并且当前窗口系统使用Direct。我希望它接收 MouseEnter/MouseLeave 事件,即使它上面有控件。一种方法是全局鼠标/键盘 Hook 。但是假设我想避免这种情况。

最佳答案

Windows 有冒泡,但它纯粹是基于消息。例如,MouseWheel 气泡,但 MouseEnter 和 Leave 都不会。添加冒泡行为在技术上是可行的,但很难做到正确。父/子树中的每个窗口都需要合作并显式冒泡到它们的父级。

无论如何,它并没有解决这个特定案例中的问题。关键问题是不能保证子控件的 MouseLeave 将确保父控件的 MouseEnter。鼠标移动消息不够准确,它们不能保证报告每个遍历的像素。当您的子窗口靠近其父窗口的边缘时,当您将鼠标移动得足够快时,很容易无法获得父窗口的 MouseEnter。

这是通过鼠标捕获解决的,Control.Capture 属性。这确保即使鼠标不再位于窗口客户端矩形内,也会生成鼠标移动消息。但是,在监视单个窗口而不是多个窗口的鼠标时效果很好。一旦你点击一个控件,这个控件本身通常想要捕获鼠标,取消你启动的那个。例如,按钮会执行此操作,它希望看到 MouseUp 事件,因此它可以重绘按钮以显示按钮弹起状态。

硬 cookies 。对于这个特定问题,我知道的唯一合适的方法是使用计时器。 200 毫秒通常就足够了,当鼠标进入时开始。在 Tick 事件处理程序中,使用 Mouse.Position 和 Control.PointToClient 检查鼠标是否仍位于外部窗口矩形内。

关于.net - 我们可以更改 Windows 中的事件路由策略吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4561267/

相关文章:

c# - 在禁用的 DataGridView 上显示垂直滚动条

winforms - 无法通过 VPN 调试 - Visual Studio 2010

.net - 如何绑定(bind) WinForm 文本框以在 TextChanged 而不是 LostFocus 上更新

javascript - 窗口对象、窗口函数和对象函数

php - 在 Windows 中的 apache 上运行 exec

c# - 如何很好地从 IEnumerable<T> 转换为 List<T>?

.net - 如何正确复制/克隆结构?我应该改用类(class)吗?

.net - 如何为两列的值范围实现查找表

winforms - NotifyIcon 使用哪种格式和大小的图标