public void ParseInputEvent(INPUT_RECORD inputRecord, Control rootElement) { if (inputRecord.EventType == EventType.MOUSE_EVENT) { MOUSE_EVENT_RECORD mouseEvent = inputRecord.MouseEvent; if (mouseEvent.dwEventFlags != MouseEventFlags.PRESSED_OR_RELEASED && mouseEvent.dwEventFlags != MouseEventFlags.MOUSE_MOVED && mouseEvent.dwEventFlags != MouseEventFlags.DOUBLE_CLICK && mouseEvent.dwEventFlags != MouseEventFlags.MOUSE_WHEELED && mouseEvent.dwEventFlags != MouseEventFlags.MOUSE_HWHEELED) { // throw new InvalidOperationException("Flags combination in mouse event was not expected."); } Point rawPosition; if (mouseEvent.dwEventFlags == MouseEventFlags.MOUSE_MOVED || mouseEvent.dwEventFlags == MouseEventFlags.PRESSED_OR_RELEASED) { rawPosition = new Point(mouseEvent.dwMousePosition.X, mouseEvent.dwMousePosition.Y); lastMousePosition = rawPosition; } else { // При событии MOUSE_WHEELED в Windows некорректно устанавливается mouseEvent.dwMousePosition // Поэтому для определения элемента, над которым производится прокручивание колёсика, мы // вынуждены сохранять координаты, полученные при предыдущем событии мыши rawPosition = lastMousePosition; } Control topMost = VisualTreeHelper.FindTopControlUnderMouse(rootElement, Control.TranslatePoint(null, rawPosition, rootElement)); // если мышь захвачена контролом, то события перемещения мыши доставляются только ему, // события, связанные с нажатием мыши - тоже доставляются только ему, вместо того // контрола, над которым событие было зарегистрировано. Такой механизм необходим, // например, для корректной обработки перемещений окон (вверх или в стороны) Control source = (inputCaptureStack.Count != 0) ? inputCaptureStack.Peek() : topMost; // No sense to further process event with no source control if (source == null) { return; } if (mouseEvent.dwEventFlags == MouseEventFlags.MOUSE_MOVED) { MouseButtonState leftMouseButtonState = getLeftButtonState(mouseEvent.dwButtonState); MouseButtonState middleMouseButtonState = getMiddleButtonState(mouseEvent.dwButtonState); MouseButtonState rightMouseButtonState = getRightButtonState(mouseEvent.dwButtonState); // MouseEventArgs mouseEventArgs = new MouseEventArgs(source, Control.PreviewMouseMoveEvent, rawPosition, leftMouseButtonState, middleMouseButtonState, rightMouseButtonState ); eventsQueue.Enqueue(mouseEventArgs); // lastLeftMouseButtonState = leftMouseButtonState; lastMiddleMouseButtonState = middleMouseButtonState; lastRightMouseButtonState = rightMouseButtonState; // detect mouse enter / mouse leave events // path to source from root element down List <Control> mouseOverStack = new List <Control>(); Control current = topMost; while (null != current) { mouseOverStack.Insert(0, current); current = current.Parent; } int index; for (index = 0; index < Math.Min(mouseOverStack.Count, prevMouseOverStack.Count); index++) { if (mouseOverStack[index] != prevMouseOverStack[index]) { break; } } for (int i = prevMouseOverStack.Count - 1; i >= index; i--) { Control control = prevMouseOverStack[i]; MouseEventArgs args = new MouseEventArgs(control, Control.MouseLeaveEvent, rawPosition, leftMouseButtonState, middleMouseButtonState, rightMouseButtonState ); eventsQueue.Enqueue(args); } for (int i = index; i < mouseOverStack.Count; i++) { // enqueue MouseEnter event Control control = mouseOverStack[i]; MouseEventArgs args = new MouseEventArgs(control, Control.MouseEnterEvent, rawPosition, leftMouseButtonState, middleMouseButtonState, rightMouseButtonState ); eventsQueue.Enqueue(args); } prevMouseOverStack.Clear(); prevMouseOverStack.AddRange(mouseOverStack); } if (mouseEvent.dwEventFlags == MouseEventFlags.PRESSED_OR_RELEASED) { // MouseButtonState leftMouseButtonState = getLeftButtonState(mouseEvent.dwButtonState); MouseButtonState middleMouseButtonState = getMiddleButtonState(mouseEvent.dwButtonState); MouseButtonState rightMouseButtonState = getRightButtonState(mouseEvent.dwButtonState); // MouseButtonEventArgs eventArgs = null; if (leftMouseButtonState != lastLeftMouseButtonState) { eventArgs = new MouseButtonEventArgs(source, leftMouseButtonState == MouseButtonState.Pressed ? Control.PreviewMouseDownEvent : Control.PreviewMouseUpEvent, rawPosition, leftMouseButtonState, lastMiddleMouseButtonState, lastRightMouseButtonState, MouseButton.Left ); } if (middleMouseButtonState != lastMiddleMouseButtonState) { eventArgs = new MouseButtonEventArgs(source, middleMouseButtonState == MouseButtonState.Pressed ? Control.PreviewMouseDownEvent : Control.PreviewMouseUpEvent, rawPosition, lastLeftMouseButtonState, middleMouseButtonState, lastRightMouseButtonState, MouseButton.Middle ); } if (rightMouseButtonState != lastRightMouseButtonState) { eventArgs = new MouseButtonEventArgs(source, rightMouseButtonState == MouseButtonState.Pressed ? Control.PreviewMouseDownEvent : Control.PreviewMouseUpEvent, rawPosition, lastLeftMouseButtonState, lastMiddleMouseButtonState, rightMouseButtonState, MouseButton.Right ); } if (eventArgs != null) { eventsQueue.Enqueue(eventArgs); } // lastLeftMouseButtonState = leftMouseButtonState; lastMiddleMouseButtonState = middleMouseButtonState; lastRightMouseButtonState = rightMouseButtonState; if (leftMouseButtonState == MouseButtonState.Pressed) { if (eventArgs != null && !autoRepeatTimerRunning) { startAutoRepeatTimer(eventArgs); } } else { if (eventArgs != null && autoRepeatTimerRunning) { stopAutoRepeatTimer( ); } } } if (mouseEvent.dwEventFlags == MouseEventFlags.MOUSE_WHEELED) { MouseWheelEventArgs args = new MouseWheelEventArgs( topMost, Control.PreviewMouseWheelEvent, rawPosition, lastLeftMouseButtonState, lastMiddleMouseButtonState, lastRightMouseButtonState, mouseEvent.dwButtonState > 0 ? 1 : -1 ); eventsQueue.Enqueue(args); } } if (inputRecord.EventType == EventType.KEY_EVENT) { KEY_EVENT_RECORD keyEvent = inputRecord.KeyEvent; KeyEventArgs eventArgs = new KeyEventArgs( ConsoleApplication.Instance.FocusManager.FocusedElement, keyEvent.bKeyDown ? Control.PreviewKeyDownEvent : Control.PreviewKeyUpEvent); eventArgs.UnicodeChar = keyEvent.UnicodeChar; eventArgs.bKeyDown = keyEvent.bKeyDown; eventArgs.dwControlKeyState = keyEvent.dwControlKeyState; eventArgs.wRepeatCount = keyEvent.wRepeatCount; eventArgs.wVirtualKeyCode = keyEvent.wVirtualKeyCode; eventArgs.wVirtualScanCode = keyEvent.wVirtualScanCode; eventsQueue.Enqueue(eventArgs); } }