// IsValid Method for RawMouseActions. Relies on the enum being flags. internal static bool IsValidRawMouseActions(RawMouseActions actions) { if (actions == RawMouseActions.None) { return(true); } if (((RawMouseActions.AttributesChanged | RawMouseActions.Activate | RawMouseActions.Deactivate | RawMouseActions.RelativeMove | RawMouseActions.AbsoluteMove | RawMouseActions.VirtualDesktopMove | RawMouseActions.Button1Press | RawMouseActions.Button1Release | RawMouseActions.Button2Press | RawMouseActions.Button2Release | RawMouseActions.Button3Press | RawMouseActions.Button3Release | RawMouseActions.Button4Press | RawMouseActions.Button4Release | RawMouseActions.Button5Press | RawMouseActions.Button5Release | RawMouseActions.VerticalWheelRotate | RawMouseActions.HorizontalWheelRotate | RawMouseActions.CancelCapture | RawMouseActions.QueryCursor) & actions) == actions) { if (!(((RawMouseActions.Deactivate & actions) == actions && RawMouseActions.Deactivate != actions) || (((RawMouseActions.Button1Press | RawMouseActions.Button1Release) & actions) == (RawMouseActions.Button1Press | RawMouseActions.Button1Release)) || (((RawMouseActions.Button2Press | RawMouseActions.Button2Release) & actions) == (RawMouseActions.Button2Press | RawMouseActions.Button2Release)) || (((RawMouseActions.Button3Press | RawMouseActions.Button3Release) & actions) == (RawMouseActions.Button3Press | RawMouseActions.Button3Release)) || (((RawMouseActions.Button4Press | RawMouseActions.Button4Release) & actions) == (RawMouseActions.Button4Press | RawMouseActions.Button4Release)) || (((RawMouseActions.Button5Press | RawMouseActions.Button5Release) & actions) == (RawMouseActions.Button5Press | RawMouseActions.Button5Release)))) { return(true); } } return(false); }
/// <summary> /// Constructs ad instance of the RawMouseInputReport class. /// </summary> /// <param name="mode"> /// The mode in which the input is being provided. /// </param> /// <param name="timestamp"> /// The time when the input occured. /// </param> /// <param name="inputSource"> /// The PresentationSource over which the mouse is moved. /// </param> /// <param name="actions"> /// The set of actions being reported. /// </param> /// <param name="x"> /// If horizontal position being reported. /// </param> /// <param name="y"> /// If vertical position being reported. /// </param> /// <param name="wheel"> /// If wheel delta being reported. /// </param> /// <param name="extraInformation"> /// Any extra information being provided along with the input. /// </param> /// <SecurityNote> /// Critical:This handles critical data in the form of PresentationSource and ExtraInformation /// TreatAsSafe:There are demands on the critical data(PresentationSource/ExtraInformation) /// </SecurityNote> private void RaisePreviewMouseMoveEvent(InputMode mode, RawMouseActions actions, PresentationSource inputSource, RoutedEvent @event, int timestamp, int pointX, int pointY, int wheel) { Assembly targetAssembly = Assembly.GetAssembly(typeof(InputEventArgs)); Type mouseInputReportType = targetAssembly.GetType("System.Windows.Input.RawMouseInputReport"); // RawMouseInputReport mouseInputReport = new RawMouseInputReport(...); Object mouseInputReport = mouseInputReportType.GetConstructors()[0].Invoke(new Object[] { mode, timestamp, inputSource, actions, pointX, pointY, wheel, IntPtr.Zero }); // mouseInputReport._isSynchronize = true; mouseInputReportType .GetField("_isSynchronize", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(mouseInputReport, true); // InputReportEventArgs inputReportEventArgs = new InputReportEventArgs(...); 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); //this.RaiseEvent((InputEventArgs)inputReportEventArgs); InputManager.Current.ProcessInput((InputEventArgs)inputReportEventArgs); }
public RawMouseInputReport( InputMode mode, int timestamp, PresentationSource inputSource, RawMouseActions actions, int x, int y, int wheel, IntPtr extraInformation) : base(inputSource, InputType.Mouse, mode, timestamp) { if (!IsValidRawMouseActions(actions)) throw new System.ComponentModel.InvalidEnumArgumentException("actions", (int)actions, typeof(RawMouseActions)); /* we pass a null state from MouseDevice.PreProcessorInput, so null is valid value for state */ _actions = actions; _x = x; _y = y; _wheel = wheel; _extraInformation = new SecurityCriticalData<IntPtr>(extraInformation); }
/// <summary> /// Constructs ad instance of the RawMouseInputReport class. /// </summary> /// <param name="mode"> /// The mode in which the input is being provided. /// </param> /// <param name="timestamp"> /// The time when the input occured. /// </param> /// <param name="inputSource"> /// The PresentationSource over which the mouse is moved. /// </param> /// <param name="actions"> /// The set of actions being reported. /// </param> /// <param name="x"> /// If horizontal position being reported. /// </param> /// <param name="y"> /// If vertical position being reported. /// </param> /// <param name="wheel"> /// If wheel delta being reported. /// </param> /// <param name="extraInformation"> /// Any extra information being provided along with the input. /// </param> public RawMouseInputReport( InputMode mode, int timestamp, PresentationSource inputSource, RawMouseActions actions, int x, int y, int wheel, IntPtr extraInformation) : base(inputSource, InputType.Mouse, mode, timestamp) { if (!IsValidRawMouseActions(actions)) { throw new System.ComponentModel.InvalidEnumArgumentException("actions", (int)actions, typeof(RawMouseActions)); } /* we pass a null state from MouseDevice.PreProcessorInput, so null is valid value for state */ _actions = actions; _x = x; _y = y; _wheel = wheel; _extraInformation = new SecurityCriticalData <IntPtr>(extraInformation); }
/// <summary> /// Construct RawMouseInputReportWrapper with mouse state. /// </summary> /// <param name="mode">mode</param> /// <param name="timestamp">timestamp</param> /// <param name="inputSource">inputSource</param> /// <param name="actions">actions</param> /// <param name="x">x</param> /// <param name="y">y</param> /// <param name="wheel">wheel</param> /// <param name="extraInformation">extraInformation</param> /// <param name="state">state</param> public RawMouseInputReportWrapper(InputMode mode, int timestamp, PresentationSource inputSource, RawMouseActions actions, int x, int y, int wheel, IntPtr extraInformation, RawMouseState state) : base() { object[] objArrayInputReportConstructor = new object[] { mode, timestamp, inputSource, actions, x, y, wheel, extraInformation, state }; this.InnerObject = Activator.CreateInstance(ReportType, objArrayInputReportConstructor); Trace.Assert(this.InnerObject != null, "Uh oh, not an input report"); }
private bool ReportInput( IntPtr hwnd, InputMode mode, int timestamp, RawMouseActions actions, int x, int y, int wheel) { // if there's no HwndSource, we shouldn't get here. But just in case... Debug.Assert(null != _source && null != _source.Value); if (_source == null || _source.Value == null) { return false; } PresentationSource source = _source.Value; CompositionTarget ct = source.CompositionTarget; // Input reports should only be generated if the window is still valid. if(_site == null || source.IsDisposed || ct == null ) { if(_active) { // We are still active, but the window is dead. Force a deactivate. actions = RawMouseActions.Deactivate; } else { return false; } } if((actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate) { // Stop tracking the mouse since we are deactivating. StopTracking(hwnd); _active = false; } else if((actions & RawMouseActions.CancelCapture) == RawMouseActions.CancelCapture) { // We have lost capture, but don't do anything else. } else if(!_active && (actions & RawMouseActions.VerticalWheelRotate) == RawMouseActions.VerticalWheelRotate) { // report mouse wheel events as if they came from the window that // is under the mouse (even though they are reported to the window // with keyboard focus) MouseDevice mouse = _site.Value.CriticalInputManager.PrimaryMouseDevice; if (mouse != null && mouse.CriticalActiveSource != null) { source = mouse.CriticalActiveSource; } } else { // If we are not active, we need to activate first. if(!_active) { // But first, check for "spurious" mouse events... // // Sometimes we get a mouse move for window "A" AFTER another // window ("B") has become active. This would cause "A" to think // that it is active, and to tell Avalon. Now both "A" and "B" think // they are active, and Avalon thinks "A" is, but REALLY, "B" is. // // Confused yet? // // To avoid this, if this window ("A") gets a mouse move, // we verify that either "A" has capture, or the mouse is over "A" IntPtr hwndToCheck = SafeNativeMethods.GetCapture(); if(hwnd != hwndToCheck) { // If we get this far, "A" does NOT have capture // - now ensure mouse is over "A" NativeMethods.POINT ptCursor = new NativeMethods.POINT(); try { UnsafeNativeMethods.GetCursorPos(ptCursor); } catch(System.ComponentModel.Win32Exception) { // Sometimes Win32 will fail this call, such as if you are // not running in the interactive desktop. For example, // a secure screen saver may be running. System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetCursorPos failed!"); } try { hwndToCheck = UnsafeNativeMethods.WindowFromPoint(ptCursor.x, ptCursor.y); } catch(System.ComponentModel.Win32Exception) { System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: WindowFromPoint failed!"); } if(hwnd != hwndToCheck) { // If we get this far: // - the mouse is NOT over "A" // - "A" does NOT have capture // We consider this a "spurious" mouse move and ignore it. (Win32 bug?) System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: Spurious mouse event received!"); return false; } } // We need to collect the current state of the mouse. // Include the activation action. actions |= RawMouseActions.Activate; // Remember that we are active. _active = true; _lastX = x; _lastY = y; //Console.WriteLine("Activating the mouse."); } // Make sure we are tracking the mouse so we know when it // leaves the window. StartTracking(hwnd); // Even if a move isn't explicitly reported, we still may need to // report one if the coordinates are different. This is to cover // some ugly edge cases with context menus and such. if((actions & RawMouseActions.AbsoluteMove) == 0) { if(x != _lastX || y != _lastY) { actions |= RawMouseActions.AbsoluteMove; } } else { _lastX = x; _lastY = y; } // record mouse motion so that GetIntermediatePoints has the // information it needs if ((actions & RawMouseActions.AbsoluteMove) != 0) { RecordMouseMove(x, y, _msgTime); } // MITIGATION: WIN32_AND_AVALON_RTL // // When a window is marked with the WS_EX_LAYOUTRTL style, Win32 // mirrors the coordinates received for mouse movement as well as // mirroring the output of drawing to a GDI DC. // // Avalon also sets up mirroring transforms so that we properly // mirror the output since we render to DirectX, not a GDI DC. // // Unfortunately, this means that our input is already mirrored // by Win32, and Avalon mirrors it again. To work around this // problem, we un-mirror the input from Win32 before passing // it into Avalon. // if((actions & (RawMouseActions.AbsoluteMove | RawMouseActions.Activate)) != 0) { try { //This has a SUC on it and accesses CriticalHandle int windowStyle = SafeNativeMethods.GetWindowStyle(new HandleRef(this, _source.Value.CriticalHandle), true); if((windowStyle & NativeMethods.WS_EX_LAYOUTRTL) == NativeMethods.WS_EX_LAYOUTRTL) { NativeMethods.RECT rcClient = new NativeMethods.RECT(); SafeNativeMethods.GetClientRect(new HandleRef(this,_source.Value.Handle), ref rcClient); x = rcClient.right - x; } } catch(System.ComponentModel.Win32Exception) { System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetWindowStyle or GetClientRect failed!"); } } } // Get the extra information sent along with the message. //There exists a SUC for this native method call IntPtr extraInformation = IntPtr.Zero; try { extraInformation = UnsafeNativeMethods.GetMessageExtraInfo(); } catch(System.ComponentModel.Win32Exception) { System.Diagnostics.Debug.WriteLine("HwndMouseInputProvider: GetMessageExtraInfo failed!"); } RawMouseInputReport report = new RawMouseInputReport(mode, timestamp, source, actions, x, y, wheel, extraInformation); bool handled = _site.Value.ReportInput(report); return handled; }
// IsValid Method for RawMouseActions. Relies on the enum being flags. internal static bool IsValidRawMouseActions(RawMouseActions actions) { if (actions == RawMouseActions.None) return true; if ((( RawMouseActions.AttributesChanged | RawMouseActions.Activate | RawMouseActions.Deactivate | RawMouseActions.RelativeMove | RawMouseActions.AbsoluteMove | RawMouseActions.VirtualDesktopMove | RawMouseActions.Button1Press | RawMouseActions.Button1Release | RawMouseActions.Button2Press | RawMouseActions.Button2Release | RawMouseActions.Button3Press | RawMouseActions.Button3Release | RawMouseActions.Button4Press | RawMouseActions.Button4Release | RawMouseActions.Button5Press | RawMouseActions.Button5Release | RawMouseActions.VerticalWheelRotate | RawMouseActions.HorizontalWheelRotate | RawMouseActions.CancelCapture | RawMouseActions.QueryCursor) & actions) == actions) { if (!(((RawMouseActions.Deactivate & actions) == actions && RawMouseActions.Deactivate != actions ) || (((RawMouseActions.Button1Press | RawMouseActions.Button1Release) & actions) == (RawMouseActions.Button1Press | RawMouseActions.Button1Release)) || (((RawMouseActions.Button2Press | RawMouseActions.Button2Release) & actions) == (RawMouseActions.Button2Press | RawMouseActions.Button2Release)) || (((RawMouseActions.Button3Press | RawMouseActions.Button3Release) & actions) == (RawMouseActions.Button3Press | RawMouseActions.Button3Release)) || (((RawMouseActions.Button4Press | RawMouseActions.Button4Release) & actions) == (RawMouseActions.Button4Press | RawMouseActions.Button4Release)) || (((RawMouseActions.Button5Press | RawMouseActions.Button5Release) & actions) == (RawMouseActions.Button5Press | RawMouseActions.Button5Release)))) { return true; } } return false; }
private RawMouseActions GetNonRedundantActions(NotifyInputEventArgs e) { RawMouseActions actions = new RawMouseActions(); // The CLR throws a null-ref exception if it tries to unbox a // null. So we have to special case that. object o = e.StagingItem.GetData(_tagNonRedundantActions); if (o != null) { actions = (RawMouseActions) o; } return actions; }
// This is used to determine whether we postpone promoting mouse move events // from stylus events. internal void SetLastRawMouseActions(RawMouseActions actions) { _lastRawMouseAction = actions; }
internal bool UpdateMouseButtonState(RawMouseActions actions) { bool updated = false; switch (actions) { case RawMouseActions.Button1Press: if (_mouseLeftButtonState != MouseButtonState.Pressed) { updated = true; _mouseLeftButtonState = MouseButtonState.Pressed; } break; case RawMouseActions.Button1Release: if (_mouseLeftButtonState != MouseButtonState.Released) { updated = true; _mouseLeftButtonState = MouseButtonState.Released; } break; case RawMouseActions.Button2Press: if (_mouseRightButtonState != MouseButtonState.Pressed) { updated = true; _mouseRightButtonState = MouseButtonState.Pressed; } break; case RawMouseActions.Button2Release: if (_mouseRightButtonState != MouseButtonState.Released) { updated = true; _mouseRightButtonState = MouseButtonState.Released; } break; } return updated; }
protected override IntPtr WndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch ((WindowMessage)msg) { case WindowMessage.LeftButtonDown: Interop.SetFocus(hWnd); RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) { RoutedEvent = Mouse.MouseDownEvent, Source = this, }); break; case WindowMessage.LeftButtonUp: RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) { RoutedEvent = Mouse.MouseUpEvent, Source = this, }); break; case WindowMessage.RightButtonDown: RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Right) { RoutedEvent = Mouse.MouseDownEvent, Source = this, }); break; case WindowMessage.RightButtonUp: RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Right) { RoutedEvent = Mouse.MouseUpEvent, Source = this, }); break; case WindowMessage.MouseMove: { int x = LOWORD(lParam.ToInt32()); int y = HIWORD(lParam.ToInt32()); Point p = this.TransformToAncestor(Application.Current.MainWindow).Transform(new Point(0, 0)); RawMouseActions actions = RawMouseActions.Activate | RawMouseActions.AbsoluteMove; RaisePreviewMouseMoveEvent( InputMode.Foreground, actions, PresentationSource.FromVisual(this), Mouse.MouseMoveEvent, Environment.TickCount, (int)(x + p.X), (int)(y + p.Y), 0); RaiseEvent(new MouseEventArgs(Mouse.PrimaryDevice, 0) { RoutedEvent = Mouse.MouseMoveEvent, Source = this }); } break; case WindowMessage.MouseWheel: short delta; switch (IntPtr.Size) { case 8: delta = (short)(wParam.ToInt64() >> 16); break; case 4: delta = (short)(wParam.ToInt32() >> 16); break; default: delta = 0; break; } RaiseEvent(new MouseWheelEventArgs(Mouse.PrimaryDevice, 0, delta) { RoutedEvent = Mouse.MouseWheelEvent, Source = this }); break; case WindowMessage.LeftButtonDoubleClick: { RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left) { RoutedEvent = Control.MouseDoubleClickEvent, Source = doubleClickControl, }); } break; case WindowMessage.RightButtonDoubleClick: RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Right) { RoutedEvent = Control.MouseDoubleClickEvent, Source = this, }); break; case WindowMessage.MiddleButtonDoubleClick: RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Middle) { RoutedEvent = Control.MouseDoubleClickEvent, Source = this, }); break; default: return(base.WndProc(hWnd, msg, wParam, lParam, ref handled)); } //handled = true; return(IntPtr.Zero); }