我可能在我的观点上有所错误 - 但至少我曾经花了相当长的时间研究过InputManager
。
我的结论是:冒泡和隧道是由InputManager
完成的。然而,调用uielement.Raise()
只会直接传递事件(无论RoutingStrategy
如何,正如Ray Burns所提到的)。
但是(猜测)根据RoutingStrategy
,InputManager
在CompositionRoot
和通过VisualTreeHlper.Hittest()
检测到的可视化树之间上下移动,并传递隧道和冒泡事件。
有一种方法可以通过InputManager引发事件,但这不是官方的,需要反射(我从另一个Stackoverflow帖子中得知):
void RaiseMouseInputReportEvent(Visual eventSource, int timestamp, int pointX, int pointY, int wheel)
{
Assembly targetAssembly = Assembly.GetAssembly(typeof(InputEventArgs));
Type mouseInputReportType = targetAssembly.GetType("System.Windows.Input.RawMouseInputReport");
Object mouseInputReport = mouseInputReportType.GetConstructors()[0].Invoke(new Object[] {
InputMode.Foreground, timestamp, PresentationSource.FromVisual(eventSource),
RawMouseActions.AbsoluteMove | RawMouseActions.Activate,
pointX, pointY, wheel, IntPtr.Zero });
mouseInputReportType.GetField("_isSynchronize", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(mouseInputReport, true);
InputEventArgs inputReportEventArgs = (InputEventArgs)targetAssembly
.GetType("System.Windows.Input.InputReportEventArgs")
.GetConstructors()[0]
.Invoke(new Object[] {
Mouse.PrimaryDevice,
mouseInputReport });
inputReportEventArgs.RoutedEvent = (RoutedEvent)typeof(InputManager)
.GetField("PreviewInputReportEvent", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
.GetValue(null);
bool handled = InputManager.Current.ProcessInput((InputEventArgs)inputReportEventArgs);
}