From 93a22c08b3223b040c3a3644fc3c4ef82fc576f0 Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Thu, 13 Aug 2020 01:52:49 -0700 Subject: Dot to show mouse move --- grapher/Models/Mouse/MouseWatcher.cs | 723 +++++++++++++++++++++++++++++++++++ 1 file changed, 723 insertions(+) create mode 100644 grapher/Models/Mouse/MouseWatcher.cs (limited to 'grapher/Models/Mouse/MouseWatcher.cs') diff --git a/grapher/Models/Mouse/MouseWatcher.cs b/grapher/Models/Mouse/MouseWatcher.cs new file mode 100644 index 0000000..9b1479e --- /dev/null +++ b/grapher/Models/Mouse/MouseWatcher.cs @@ -0,0 +1,723 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace grapher.Models.Mouse +{ + public class MouseWatcher + { + /// + /// Enumeration containing HID usage page flags. + /// + public enum HIDUsagePage : ushort + { + /// Unknown usage page. + Undefined = 0x00, + /// Generic desktop controls. + Generic = 0x01, + /// Simulation controls. + Simulation = 0x02, + /// Virtual reality controls. + VR = 0x03, + /// Sports controls. + Sport = 0x04, + /// Games controls. + Game = 0x05, + /// Keyboard controls. + Keyboard = 0x07, + /// LED controls. + LED = 0x08, + /// Button. + Button = 0x09, + /// Ordinal. + Ordinal = 0x0A, + /// Telephony. + Telephony = 0x0B, + /// Consumer. + Consumer = 0x0C, + /// Digitizer. + Digitizer = 0x0D, + /// Physical interface device. + PID = 0x0F, + /// Unicode. + Unicode = 0x10, + /// Alphanumeric display. + AlphaNumeric = 0x14, + /// Medical instruments. + Medical = 0x40, + /// Monitor page 0. + MonitorPage0 = 0x80, + /// Monitor page 1. + MonitorPage1 = 0x81, + /// Monitor page 2. + MonitorPage2 = 0x82, + /// Monitor page 3. + MonitorPage3 = 0x83, + /// Power page 0. + PowerPage0 = 0x84, + /// Power page 1. + PowerPage1 = 0x85, + /// Power page 2. + PowerPage2 = 0x86, + /// Power page 3. + PowerPage3 = 0x87, + /// Bar code scanner. + BarCode = 0x8C, + /// Scale page. + Scale = 0x8D, + /// Magnetic strip reading devices. + MSR = 0x8E + } + + /// + /// Enumeration containing the HID usage values. + /// + public enum HIDUsage : ushort + { + /// + Pointer = 0x01, + /// + Mouse = 0x02, + /// + Joystick = 0x04, + /// + Gamepad = 0x05, + /// + Keyboard = 0x06, + /// + Keypad = 0x07, + /// + SystemControl = 0x80, + /// + X = 0x30, + /// + Y = 0x31, + /// + Z = 0x32, + /// + RelativeX = 0x33, + /// + RelativeY = 0x34, + /// + RelativeZ = 0x35, + /// + Slider = 0x36, + /// + Dial = 0x37, + /// + Wheel = 0x38, + /// + HatSwitch = 0x39, + /// + CountedBuffer = 0x3A, + /// + ByteCount = 0x3B, + /// + MotionWakeup = 0x3C, + /// + VX = 0x40, + /// + VY = 0x41, + /// + VZ = 0x42, + /// + VBRX = 0x43, + /// + VBRY = 0x44, + /// + VBRZ = 0x45, + /// + VNO = 0x46, + /// + SystemControlPower = 0x81, + /// + SystemControlSleep = 0x82, + /// + SystemControlWake = 0x83, + /// + SystemControlContextMenu = 0x84, + /// + SystemControlMainMenu = 0x85, + /// + SystemControlApplicationMenu = 0x86, + /// + SystemControlHelpMenu = 0x87, + /// + SystemControlMenuExit = 0x88, + /// + SystemControlMenuSelect = 0x89, + /// + SystemControlMenuRight = 0x8A, + /// + SystemControlMenuLeft = 0x8B, + /// + SystemControlMenuUp = 0x8C, + /// + SystemControlMenuDown = 0x8D, + /// + KeyboardNoEvent = 0x00, + /// + KeyboardRollover = 0x01, + /// + KeyboardPostFail = 0x02, + /// + KeyboardUndefined = 0x03, + /// + KeyboardaA = 0x04, + /// + KeyboardzZ = 0x1D, + /// + Keyboard1 = 0x1E, + /// + Keyboard0 = 0x27, + /// + KeyboardLeftControl = 0xE0, + /// + KeyboardLeftShift = 0xE1, + /// + KeyboardLeftALT = 0xE2, + /// + KeyboardLeftGUI = 0xE3, + /// + KeyboardRightControl = 0xE4, + /// + KeyboardRightShift = 0xE5, + /// + KeyboardRightALT = 0xE6, + /// + KeyboardRightGUI = 0xE7, + /// + KeyboardScrollLock = 0x47, + /// + KeyboardNumLock = 0x53, + /// + KeyboardCapsLock = 0x39, + /// + KeyboardF1 = 0x3A, + /// + KeyboardF12 = 0x45, + /// + KeyboardReturn = 0x28, + /// + KeyboardEscape = 0x29, + /// + KeyboardDelete = 0x2A, + /// + KeyboardPrintScreen = 0x46, + /// + LEDNumLock = 0x01, + /// + LEDCapsLock = 0x02, + /// + LEDScrollLock = 0x03, + /// + LEDCompose = 0x04, + /// + LEDKana = 0x05, + /// + LEDPower = 0x06, + /// + LEDShift = 0x07, + /// + LEDDoNotDisturb = 0x08, + /// + LEDMute = 0x09, + /// + LEDToneEnable = 0x0A, + /// + LEDHighCutFilter = 0x0B, + /// + LEDLowCutFilter = 0x0C, + /// + LEDEqualizerEnable = 0x0D, + /// + LEDSoundFieldOn = 0x0E, + /// + LEDSurroundFieldOn = 0x0F, + /// + LEDRepeat = 0x10, + /// + LEDStereo = 0x11, + /// + LEDSamplingRateDirect = 0x12, + /// + LEDSpinning = 0x13, + /// + LEDCAV = 0x14, + /// + LEDCLV = 0x15, + /// + LEDRecordingFormatDet = 0x16, + /// + LEDOffHook = 0x17, + /// + LEDRing = 0x18, + /// + LEDMessageWaiting = 0x19, + /// + LEDDataMode = 0x1A, + /// + LEDBatteryOperation = 0x1B, + /// + LEDBatteryOK = 0x1C, + /// + LEDBatteryLow = 0x1D, + /// + LEDSpeaker = 0x1E, + /// + LEDHeadset = 0x1F, + /// + LEDHold = 0x20, + /// + LEDMicrophone = 0x21, + /// + LEDCoverage = 0x22, + /// + LEDNightMode = 0x23, + /// + LEDSendCalls = 0x24, + /// + LEDCallPickup = 0x25, + /// + LEDConference = 0x26, + /// + LEDStandBy = 0x27, + /// + LEDCameraOn = 0x28, + /// + LEDCameraOff = 0x29, + /// + LEDOnLine = 0x2A, + /// + LEDOffLine = 0x2B, + /// + LEDBusy = 0x2C, + /// + LEDReady = 0x2D, + /// + LEDPaperOut = 0x2E, + /// + LEDPaperJam = 0x2F, + /// + LEDRemote = 0x30, + /// + LEDForward = 0x31, + /// + LEDReverse = 0x32, + /// + LEDStop = 0x33, + /// + LEDRewind = 0x34, + /// + LEDFastForward = 0x35, + /// + LEDPlay = 0x36, + /// + LEDPause = 0x37, + /// + LEDRecord = 0x38, + /// + LEDError = 0x39, + /// + LEDSelectedIndicator = 0x3A, + /// + LEDInUseIndicator = 0x3B, + /// + LEDMultiModeIndicator = 0x3C, + /// + LEDIndicatorOn = 0x3D, + /// + LEDIndicatorFlash = 0x3E, + /// + LEDIndicatorSlowBlink = 0x3F, + /// + LEDIndicatorFastBlink = 0x40, + /// + LEDIndicatorOff = 0x41, + /// + LEDFlashOnTime = 0x42, + /// + LEDSlowBlinkOnTime = 0x43, + /// + LEDSlowBlinkOffTime = 0x44, + /// + LEDFastBlinkOnTime = 0x45, + /// + LEDFastBlinkOffTime = 0x46, + /// + LEDIndicatorColor = 0x47, + /// + LEDRed = 0x48, + /// + LEDGreen = 0x49, + /// + LEDAmber = 0x4A, + /// + LEDGenericIndicator = 0x3B, + /// + TelephonyPhone = 0x01, + /// + TelephonyAnsweringMachine = 0x02, + /// + TelephonyMessageControls = 0x03, + /// + TelephonyHandset = 0x04, + /// + TelephonyHeadset = 0x05, + /// + TelephonyKeypad = 0x06, + /// + TelephonyProgrammableButton = 0x07, + /// + SimulationRudder = 0xBA, + /// + SimulationThrottle = 0xBB + } + + /// Enumeration containing flags for a raw input device. + [Flags()] + public enum RawInputDeviceFlags + { + /// No flags. + None = 0, + /// If set, this removes the top level collection from the inclusion list. This tells the operating system to stop reading from a device which matches the top level collection. + Remove = 0x00000001, + /// If set, this specifies the top level collections to exclude when reading a complete usage page. This flag only affects a TLC whose usage page is already specified with PageOnly. + Exclude = 0x00000010, + /// If set, this specifies all devices whose top level collection is from the specified usUsagePage. Note that Usage must be zero. To exclude a particular top level collection, use Exclude. + PageOnly = 0x00000020, + /// If set, this prevents any devices specified by UsagePage or Usage from generating legacy messages. This is only for the mouse and keyboard. + NoLegacy = 0x00000030, + /// If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that WindowHandle must be specified. + InputSink = 0x00000100, + /// If set, the mouse button click does not activate the other window. + CaptureMouse = 0x00000200, + /// If set, the application-defined keyboard device hotkeys are not handled. However, the system hotkeys; for example, ALT+TAB and CTRL+ALT+DEL, are still handled. By default, all keyboard hotkeys are handled. NoHotKeys can be specified even if NoLegacy is not specified and WindowHandle is NULL. + NoHotKeys = 0x00000200, + /// If set, application keys are handled. NoLegacy must be specified. Keyboard only. + AppKeys = 0x00000400 + } + + /// Value type for raw input devices. + [StructLayout(LayoutKind.Sequential)] + public struct RAWINPUTDEVICE + { + /// Top level collection Usage page for the raw input device. + public HIDUsagePage UsagePage; + /// Top level collection Usage for the raw input device. + public HIDUsage Usage; + /// Mode flag that specifies how to interpret the information provided by UsagePage and Usage. + public RawInputDeviceFlags Flags; + /// Handle to the target device. If NULL, it follows the keyboard focus. + public IntPtr WindowHandle; + } + + /// + /// Contains the raw input from a device. + /// + [StructLayout(LayoutKind.Sequential)] + public struct RawInput + { + /// + /// Header for the data. + /// + public RAWINPUTHEADER Header; + public Union Data; + [StructLayout(LayoutKind.Explicit)] + public struct Union + { + /// + /// Mouse raw input data. + /// + [FieldOffset(0)] + public RawMouse Mouse; + /// + /// Keyboard raw input data. + /// + [FieldOffset(0)] + public RawKeyboard Keyboard; + /// + /// HID raw input data. + /// + [FieldOffset(0)] + public RawHID HID; + } + } + + /// + /// Value type for raw input from a HID. + /// + [StructLayout(LayoutKind.Sequential)] + public struct RawHID + { + /// Size of the HID data in bytes. + public int Size; + /// Number of HID in Data. + public int Count; + /// Data for the HID. + public IntPtr Data; + } + + /// + /// Value type for a raw input header. + /// + [StructLayout(LayoutKind.Sequential)] + public struct RAWINPUTHEADER + { + /// Type of device the input is coming from. + public RawInputType Type; + /// Size of the packet of data. + public int Size; + /// Handle to the device sending the data. + public IntPtr Device; + /// wParam from the window message. + public IntPtr wParam; + } + + /// + /// Enumeration containing the type device the raw input is coming from. + /// + public enum RawInputType + { + /// + /// Mouse input. + /// + Mouse = 0, + + /// + /// Keyboard input. + /// + Keyboard = 1, + + /// + /// Human interface device input. + /// + HID = 2, + + /// + /// Another device that is not the keyboard or the mouse. + /// + Other = 3 + } + + /// + /// Contains information about the state of the mouse. + /// + [StructLayout(LayoutKind.Sequential)] + public struct RawMouse + { + /// + /// The mouse state. + /// + public RawMouseFlags Flags; + + [StructLayout(LayoutKind.Explicit)] + public struct Data + { + [FieldOffset(0)] + public uint Buttons; + /// + /// If the mouse wheel is moved, this will contain the delta amount. + /// + [FieldOffset(2)] + public ushort ButtonData; + /// + /// Flags for the event. + /// + [FieldOffset(0)] + public RawMouseButtons ButtonFlags; + } + + public Data _Data; + + /// + /// Raw button data. + /// + public uint RawButtons; + /// + /// The motion in the X direction. This is signed relative motion or + /// absolute motion, depending on the value of usFlags. + /// + public int LastX; + /// + /// The motion in the Y direction. This is signed relative motion or absolute motion, + /// depending on the value of usFlags. + /// + public int LastY; + /// + /// The device-specific additional information for the event. + /// + public uint ExtraInformation; + } + + /// + /// Enumeration containing the flags for raw mouse data. + /// + [Flags()] + public enum RawMouseFlags + : ushort + { + /// Relative to the last position. + MoveRelative = 0, + /// Absolute positioning. + MoveAbsolute = 1, + /// Coordinate data is mapped to a virtual desktop. + VirtualDesktop = 2, + /// Attributes for the mouse have changed. + AttributesChanged = 4 + } + + /// + /// Enumeration containing the button data for raw mouse input. + /// + [Flags()] + public enum RawMouseButtons + : ushort + { + /// No button. + None = 0, + /// Left (button 1) down. + LeftDown = 0x0001, + /// Left (button 1) up. + LeftUp = 0x0002, + /// Right (button 2) down. + RightDown = 0x0004, + /// Right (button 2) up. + RightUp = 0x0008, + /// Middle (button 3) down. + MiddleDown = 0x0010, + /// Middle (button 3) up. + MiddleUp = 0x0020, + /// Button 4 down. + Button4Down = 0x0040, + /// Button 4 up. + Button4Up = 0x0080, + /// Button 5 down. + Button5Down = 0x0100, + /// Button 5 up. + Button5Up = 0x0200, + /// Mouse wheel moved. + MouseWheel = 0x0400 + } + + /// + /// Value type for raw input from a keyboard. + /// + [StructLayout(LayoutKind.Sequential)] + public struct RawKeyboard + { + /// Scan code for key depression. + public short MakeCode; + /// Scan code information. + public RawKeyboardFlags Flags; + /// Reserved. + public short Reserved; + /// Virtual key code. + public ushort VirtualKey; + /// Corresponding window message. + public uint Message; + /// Extra information. + public int ExtraInformation; + } + + /// + /// Enumeration containing flags for raw keyboard input. + /// + [Flags] + public enum RawKeyboardFlags : ushort + { + /// + KeyMake = 0, + /// + KeyBreak = 1, + /// + KeyE0 = 2, + /// + KeyE1 = 4, + /// + TerminalServerSetLED = 8, + /// + TerminalServerShadow = 0x10, + /// + TerminalServerVKPACKET = 0x20 + } + + /// + /// Enumeration contanining the command types to issue. + /// + public enum RawInputCommand + { + /// + /// Get input data. + /// + Input = 0x10000003, + /// + /// Get header data. + /// + Header = 0x10000005 + } + + [DllImport("user32.dll")] + public static extern bool RegisterRawInputDevices([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] RAWINPUTDEVICE[] pRawInputDevices, int uiNumDevices, int cbSize); + + /// + /// Function to retrieve raw input data. + /// + /// Handle to the raw input. + /// Command to issue when retrieving data. + /// Raw input data. + /// Number of bytes in the array. + /// Size of the header. + /// 0 if successful if pData is null, otherwise number of bytes if pData is not null. + [DllImport("user32.dll")] + public static extern int GetRawInputData(IntPtr hRawInput, RawInputCommand uiCommand, out RawInput pData, ref int pcbSize, int cbSizeHeader); + + public MouseWatcher(Form containingForm, Label display, AccelCharts accelCharts) + { + ContainingForm = containingForm; + Display = display; + AccelCharts = accelCharts; + + RAWINPUTDEVICE device = new RAWINPUTDEVICE(); + device.WindowHandle = ContainingForm.Handle; + device.UsagePage = HIDUsagePage.Generic; + device.Usage = HIDUsage.Mouse; + device.Flags = RawInputDeviceFlags.InputSink; + + RAWINPUTDEVICE[] devices = new RAWINPUTDEVICE[1]; + devices[0] = device; + RegisterRawInputDevices(devices, 1, Marshal.SizeOf(typeof(RAWINPUTDEVICE))); + } + + Form ContainingForm { get; } + + Label Display { get; } + + AccelCharts AccelCharts { get; } + + public void OnMouseMove(int x, int y) + { + Display.Text = $"Last (x, y): ({x}, {y})"; + AccelCharts.MakeDots(x, y); + } + + public void ReadMouseMove(Message message) + { + RawInput rawInput = new RawInput(); + int outSize = 0; + int size = Marshal.SizeOf(typeof(RawInput)); + + outSize = GetRawInputData((IntPtr)message.LParam, RawInputCommand.Input, out rawInput, ref size, Marshal.SizeOf(typeof(RAWINPUTHEADER))); + + if (rawInput.Data.Mouse.LastX != 0 || rawInput.Data.Mouse.LastY != 0) + { + OnMouseMove(rawInput.Data.Mouse.LastX, rawInput.Data.Mouse.LastY); + } + + } + } +} -- cgit v1.2.3 From 32323636b4b5390c114fc2a6d845b7621a983cdc Mon Sep 17 00:00:00 2001 From: Jacob Palecki Date: Thu, 13 Aug 2020 20:56:41 -0700 Subject: Fix initial points, add poll time constant --- grapher/Models/Mouse/MouseWatcher.cs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'grapher/Models/Mouse/MouseWatcher.cs') diff --git a/grapher/Models/Mouse/MouseWatcher.cs b/grapher/Models/Mouse/MouseWatcher.cs index 9b1479e..fea4e2d 100644 --- a/grapher/Models/Mouse/MouseWatcher.cs +++ b/grapher/Models/Mouse/MouseWatcher.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -691,18 +692,21 @@ namespace grapher.Models.Mouse RAWINPUTDEVICE[] devices = new RAWINPUTDEVICE[1]; devices[0] = device; RegisterRawInputDevices(devices, 1, Marshal.SizeOf(typeof(RAWINPUTDEVICE))); + PollTime = 1; } - Form ContainingForm { get; } + private Form ContainingForm { get; } - Label Display { get; } + private Label Display { get; } - AccelCharts AccelCharts { get; } + private AccelCharts AccelCharts { get; } - public void OnMouseMove(int x, int y) + private double PollTime { get; } + + public void OnMouseMove(int x, int y, double timeInMs) { Display.Text = $"Last (x, y): ({x}, {y})"; - AccelCharts.MakeDots(x, y); + AccelCharts.MakeDots(x, y, timeInMs); } public void ReadMouseMove(Message message) @@ -715,7 +719,7 @@ namespace grapher.Models.Mouse if (rawInput.Data.Mouse.LastX != 0 || rawInput.Data.Mouse.LastY != 0) { - OnMouseMove(rawInput.Data.Mouse.LastX, rawInput.Data.Mouse.LastY); + OnMouseMove(rawInput.Data.Mouse.LastX, rawInput.Data.Mouse.LastY, PollTime); } } -- cgit v1.2.3