Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can we change event routing strategy in windows?

In .NET window forms a form have collection of control and internally all of them is just wrap around window subsystem provided by Microsoft windows. Somewhat similar to MFC which is a shallow wrapper around window api. The controls in a form/window create a tree structure and events are received by the leaf nodes e.g. MouseMove event will be receive by window/control directly underneath the mouse.

But in presentation framework microsoft provided RoutedEvent which can have one of following strategies

  1. Tunnel The routed event uses a tunneling strategy, where the event instance routes downwards through the tree, from root to source element.
  2. Bubble The routed event uses a bubbling strategy, where the event instance routes upwards through the tree, from event source to root.
  3. Direct The routed event does not route through an element tree.

My guess is that presentation framework create just one main window and does the drawing by itself for child elements to support the event routing strategies

Now can I change this strategy in my normal window form. I want Tunnel or Bubble and currently window system uses Direct. I want it to receive MouseEnter/MouseLeave event even if there are controls on top of it. One way is Global mouse/keyboard hook. But let say i want to avoid that.

like image 551
particle Avatar asked Oct 16 '25 03:10

particle


1 Answers

Windows has bubbling but it is purely based on the message. MouseWheel bubbles for example, but neither MouseEnter nor Leave do. Adding bubbling behavior is technically possible but very hard to get right. Every window in the parent/child tree needs to co-operate and bubble to their parent explicitly.

It doesn't solve the problem in this specific case anyway. Key issue is that there's no guarantee that a MouseLeave for a child control will ensure a MouseEnter for the parent. Mouse move messages are not accurate enough, they don't guarantee that every traversed pixel is reported. When you have a child window close to the edge of its parent, it is quite easy to not get the MouseEnter for the parent when you move the mouse fast enough.

This is solved with mouse capture, the Control.Capture property. That ensures a mouse move message is generated even when the mouse is no longer inside the window client rectangle. However, that works well when monitoring the mouse for a single window, not for multiple windows. As soon as you click a control, the control itself usually wants to capture the mouse, canceling the one you started. A button does so for example, it wants to see the MouseUp event so it can redraw the button to show the button-up state.

Tough cookies. The only decent approach I know for this particular problem is to use a Timer. 200 msec is usually good enough, start it when the mouse enters. In the Tick event handler, use Mouse.Position and Control.PointToClient to check if the mouse is still located inside the outer window rectangle.

like image 184
Hans Passant Avatar answered Oct 19 '25 13:10

Hans Passant