【问题标题】:Can we change event routing strategy in windows?我们可以在 Windows 中更改事件路由策略吗?
【发布时间】:2011-06-01 11:14:30
【问题描述】:

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

但在演示框架中,微软提供了RoutedEvent,它可以有以下策略之一

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

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

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

【问题讨论】:

  • 它可以在 WPF 中完成,我说的是 Windows 窗体以及在 Microsoft Windows 中使用 CreateWindow() API 创建的任何窗口。

标签: .net winforms window


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    • 2022-12-20
    • 2015-12-05
    • 2014-12-25
    • 1970-01-01
    相关资源
    最近更新 更多