Можем ли мы изменить стратегию маршрутизации событий в Windows? - PullRequest
3 голосов
/ 30 декабря 2010

В оконных формах .NET форма имеет набор элементов управления, и внутренне все они просто обернуты вокруг оконной подсистемы, предоставляемой Microsoft Windows.Несколько похоже на MFC, который является мелкой оберткой вокруг окна API.Элементы управления в форме / окне создают древовидную структуру, а конечные узлы получают события, например, событие MouseMove будет получено окном / элементом управления непосредственно под мышью.

Но в рамках представления Microsoft предоставила RoutedEvent , которая может иметь одну из следующих стратегий

  1. Tunnel В маршрутизируемом событии используется стратегия туннелирования,где экземпляр события направляется вниз по дереву от корневого элемента к исходному элементу.
  2. Bubble В маршрутизируемом событии используется стратегия пузырьков, когда экземпляр события направляется вверх по дереву из источника событияroot.
  3. Direct Маршрутизируемое событие не проходит через дерево элементов.

Я предполагаю, что структура представления создает только одно главное окнои выполняет рисование для дочерних элементов для поддержки стратегий маршрутизации событий

Теперь я могу изменить эту стратегию в своей обычной оконной форме.Я хочу Tunnel или Bubble , и в настоящее время оконная система использует Direct .Я хочу, чтобы он получал событие MouseEnter / MouseLeave, даже если поверх него есть элементы управления.Одним из способов является глобальное подключение мыши / клавиатуры.Но, скажем, я хочу этого избежать.

1 Ответ

7 голосов
/ 30 декабря 2010

В Windows всплывают пузырьки, но они основаны исключительно на сообщении.MouseWheel пузырится, например, но ни MouseEnter, ни Leave не делают.Добавление пузырящего поведения технически возможно, но очень трудно понять правильно.Каждое окно в родительском / дочернем дереве должно взаимодействовать и явно связываться с их родителями.

В любом случае, это не решает проблему в данном конкретном случае.Ключевая проблема заключается в том, что нет гарантии, что MouseLeave для дочернего элемента управления обеспечит MouseEnter для родителя.Сообщения о перемещении мыши недостаточно точны, они не гарантируют, что сообщается о каждом пройденном пикселе.Когда у вас есть дочернее окно близко к краю его родителя, довольно просто не получить MouseEnter для родителя, когда вы перемещаете мышь достаточно быстро.

Это решается с помощью захвата мыши, Control.Захват собственности.Это гарантирует, что сообщение о перемещении мыши генерируется, даже если мышь больше не находится внутри прямоугольника клиента окна.Однако это хорошо работает при мониторинге мыши для одного окна, а не для нескольких окон.Как только вы нажимаете на элемент управления, сам элемент управления обычно хочет захватить мышь, отменяя тот, который вы запустили.Например, кнопка делает это, она хочет видеть событие MouseUp, чтобы она могла перерисовать кнопку, чтобы показать состояние кнопки.

Жесткие файлы cookie.Единственный достойный подход, который я знаю для этой конкретной проблемы, это использовать таймер.200 мсек обычно достаточно, запустите его, когда мышь войдет.В обработчике событий Tick используйте Mouse.Position и Control.PointToClient, чтобы проверить, находится ли мышь по-прежнему внутри прямоугольника внешнего окна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...