From d7e29c7ee48f42058bfd056319ef0a175196510b Mon Sep 17 00:00:00 2001 From: Jeroen Saey Date: Wed, 8 Oct 2025 11:38:16 +0200 Subject: [PATCH] Updated console message loop --- Analyzer/EonaCat.HID.Analyzer.csproj | 217 +++++++++++----------- Analyzer/MainForm.cs | 122 +++++++----- EonaCat.HID.Console/Program.cs | 2 +- EonaCat.HID/EonaCat.HID.csproj | 111 +++++------ EonaCat.HID/HidFactory.cs | 4 +- EonaCat.HID/HidLinux.cs | 42 +++-- EonaCat.HID/HidWindows.cs | 12 ++ EonaCat.HID/Managers/HidManagerMac.cs | 16 +- EonaCat.HID/Managers/HidManagerWindows.cs | 204 ++++++++++++++++---- 9 files changed, 452 insertions(+), 278 deletions(-) diff --git a/Analyzer/EonaCat.HID.Analyzer.csproj b/Analyzer/EonaCat.HID.Analyzer.csproj index 1258cdd..8153f56 100644 --- a/Analyzer/EonaCat.HID.Analyzer.csproj +++ b/Analyzer/EonaCat.HID.Analyzer.csproj @@ -1,115 +1,116 @@ - - - - - Debug - AnyCPU - {61994020-DB89-4621-BA4B-7347A2142CFF} - WinExe - Properties - EonaCat.HID - EonaCat HID Analyzer - v4.8 - 512 - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - Form - - - AboutBox.cs - - - Form - - - MainForm.cs - - - - - AboutBox.cs - Designer - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - {00403bd6-7a26-4971-29d3-8a7849aac770} - EonaCat.HID - - - + + + + + Debug + AnyCPU + {61994020-DB89-4621-BA4B-7347A2142CFF} + WinExe + Properties + EonaCat.HID + EonaCat HID Analyzer + v4.8 + 512 + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + Form + + + AboutBox.cs + + + Form + + + MainForm.cs + + + + + AboutBox.cs + Designer + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + {00403bd6-7a26-4971-29d3-8a7849aac770} + EonaCat.HID + + + + --> \ No newline at end of file diff --git a/Analyzer/MainForm.cs b/Analyzer/MainForm.cs index fc2ca95..8e17514 100644 --- a/Analyzer/MainForm.cs +++ b/Analyzer/MainForm.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; +using System.Windows.Threading; namespace EonaCat.HID.Analyzer { @@ -42,7 +43,8 @@ namespace EonaCat.HID.Analyzer public async Task RefreshDevicesAsync(ushort? vendorId = null, ushort? productId = null) { - _deviceList = await _deviceManager.EnumerateAsync(vendorId, productId).ConfigureAwait(false); + toolStripStatusLabel1.Text = "Refreshing devices, this may take a while..."; + _deviceList = await _deviceManager.EnumerateAsync(vendorId, productId); } private void MainForm_Load(object sender, System.EventArgs e) @@ -57,12 +59,12 @@ namespace EonaCat.HID.Analyzer } } - private void MainForm_Shown(object sender, System.EventArgs e) + private async void MainForm_Shown(object sender, System.EventArgs e) { try { - RefreshDevicesAsync(); - UpdateDeviceList(); + await RefreshDevicesAsync().ConfigureAwait(false); + UpdateDeviceListAsync(); toolStripStatusLabel1.Text = "Please select device and click open to start."; } catch (Exception ex) @@ -94,44 +96,62 @@ namespace EonaCat.HID.Analyzer })); } - private void UpdateDeviceList() - { - dataGridView1.SelectionChanged -= DataGridView1_SelectionChanged; - dataGridView1.Rows.Clear(); - - for (int i = 0; i < _deviceList.Count(); i++) - { - IHid device = _deviceList.ElementAt(i); - - var deviceName = ""; - var deviceManufacturer = ""; - var deviceSerialNumber = ""; - - deviceName = device.ProductName; - deviceManufacturer = device.Manufacturer; - deviceSerialNumber = device.SerialNumber; - var isWritingSupported = device.IsWritingSupport; - var isReadingSupported = device.IsReadingSupport; - - var row = new string[] - { - (i + 1).ToString(), - deviceName, - deviceManufacturer, - deviceSerialNumber, - isReadingSupported.ToString(), - isWritingSupported.ToString(), - device.InputReportByteLength.ToString(), - device.OutputReportByteLength.ToString(), - device.FeatureReportByteLength.ToString(), - $"Vendor:{device.VendorId:X4} Product:{device.ProductId:X4} Revision:{device.VendorId:X4}", - device.DevicePath - }; - - dataGridView1.Rows.Add(row); - } - dataGridView1.SelectionChanged += DataGridView1_SelectionChanged; - DataGridView1_SelectionChanged(this, null); + private async Task UpdateDeviceListAsync() + { + if (_deviceList == null || !_deviceList.Any()) + { + return; + } + + // Capture the data in a local variable so the UI update can happen in one go + var rows = new List(); + for (int i = 0; i < _deviceList.Count(); i++) + { + IHid device = _deviceList.ElementAt(i); + + var row = new string[] + { + (i + 1).ToString(), + device.ProductName, + device.Manufacturer, + device.SerialNumber, + device.IsReadingSupport.ToString(), + device.IsWritingSupport.ToString(), + device.InputReportByteLength.ToString(), + device.OutputReportByteLength.ToString(), + device.FeatureReportByteLength.ToString(), + $"Vendor:{device.VendorId:X4} Product:{device.ProductId:X4} Revision:{device.VendorId:X4}", + device.DevicePath + }; + + rows.Add(row); + } + + if (dataGridView1.InvokeRequired) + { + dataGridView1.Invoke(new Action(() => + { + dataGridView1.SelectionChanged -= DataGridView1_SelectionChanged; + dataGridView1.Rows.Clear(); + foreach (var row in rows) + { + dataGridView1.Rows.Add(row); + } + dataGridView1.SelectionChanged += DataGridView1_SelectionChanged; + DataGridView1_SelectionChanged(this, null); + })); + } + else + { + dataGridView1.SelectionChanged -= DataGridView1_SelectionChanged; + dataGridView1.Rows.Clear(); + foreach (var row in rows) + { + dataGridView1.Rows.Add(row); + } + dataGridView1.SelectionChanged += DataGridView1_SelectionChanged; + DataGridView1_SelectionChanged(this, null); + } } private void PopupException(string message, string caption = "Exception") @@ -178,12 +198,12 @@ namespace EonaCat.HID.Analyzer } } - private void ToolStripButtonReload_Click(object sender, EventArgs e) + private async void ToolStripButtonReload_Click(object sender, EventArgs e) { try { - RefreshDevicesAsync(); - UpdateDeviceList(); + await RefreshDevicesAsync().ConfigureAwait(false); + UpdateDeviceListAsync(); } catch (Exception ex) { @@ -191,7 +211,7 @@ namespace EonaCat.HID.Analyzer } } - private void ToolStripButtonFilter_Click(object sender, EventArgs e) + private async void ToolStripButtonFilter_Click(object sender, EventArgs e) { try { @@ -203,8 +223,8 @@ namespace EonaCat.HID.Analyzer vid = ushort.Parse(str[0], NumberStyles.AllowHexSpecifier); pid = ushort.Parse(str[1], NumberStyles.AllowHexSpecifier); } - RefreshDevicesAsync(vid, pid); - UpdateDeviceList(); + await RefreshDevicesAsync(vid, pid).ConfigureAwait(false); + UpdateDeviceListAsync(); } catch (Exception ex) { @@ -341,12 +361,12 @@ namespace EonaCat.HID.Analyzer } var report = await _device.ReadInputReportAsync(); - if (report == null || report.Data.Length < 2) + if (report == null || report.Data.Length < 2) { AppendEventLog("Received report is null or is too short to contain a valid Report ID.", Color.Red); return; - } - + } + var str = string.Format("Rx Input Report [{0}] <-- {1}", report.Data.Length, BitConverter.ToString(report.Data)); AppendEventLog(str, Color.Blue); } diff --git a/EonaCat.HID.Console/Program.cs b/EonaCat.HID.Console/Program.cs index f05197a..8e562d9 100644 --- a/EonaCat.HID.Console/Program.cs +++ b/EonaCat.HID.Console/Program.cs @@ -34,7 +34,7 @@ namespace EonaCat.HID.Example Console.WriteLine($"Removed Device --> VID: {e.Device.VendorId:X4}, PID: {e.Device.ProductId:X4}"); }; - RefreshDevicesAsync(); + await RefreshDevicesAsync().ConfigureAwait(false); if (!_deviceList.Any()) { diff --git a/EonaCat.HID/EonaCat.HID.csproj b/EonaCat.HID/EonaCat.HID.csproj index 70d8eb9..a8a2492 100644 --- a/EonaCat.HID/EonaCat.HID.csproj +++ b/EonaCat.HID/EonaCat.HID.csproj @@ -1,55 +1,56 @@ - - - - net46;net6.0 - true - EonaCat (Jeroen Saey) - Copyright 2024 EonaCat (Jeroen Saey) - latest - EonaCat.HID - 1.0.5 - EonaCat.HID - EonaCat (Jeroen Saey) - HID Devices - LICENSE - - icon.png - https://www.nuget.org/packages/EonaCat.HID/ - usb; hid; Jeroen;Saey - True - README.md - - - - - True - \ - - - True - \ - - - True - \ - - - - - - - - - - ..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.Windows.Forms.dll - - - - - - True - \ - - - - + + + + net48;net6.0 + true + EonaCat (Jeroen Saey) + Copyright 2024 EonaCat (Jeroen Saey) + latest + EonaCat.HID + 1.0.6 + EonaCat.HID + EonaCat (Jeroen Saey) + HID Devices + LICENSE + + icon.png + https://www.nuget.org/packages/EonaCat.HID/ + usb; hid; Jeroen;Saey + True + README.md + + + + + True + \ + + + True + \ + + + True + \ + + + + + + + + + + + True + \ + + + + + + 4.8.2 + + + + diff --git a/EonaCat.HID/HidFactory.cs b/EonaCat.HID/HidFactory.cs index 8333051..62be540 100644 --- a/EonaCat.HID/HidFactory.cs +++ b/EonaCat.HID/HidFactory.cs @@ -50,7 +50,9 @@ namespace EonaCat.HID { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - return new Managers.Windows.HidManagerWindows(); + var deviceManager = new Managers.Windows.HidManagerWindows(); + deviceManager.Start(); + return deviceManager; } if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) diff --git a/EonaCat.HID/HidLinux.cs b/EonaCat.HID/HidLinux.cs index 96ae9ae..c58ac12 100644 --- a/EonaCat.HID/HidLinux.cs +++ b/EonaCat.HID/HidLinux.cs @@ -59,10 +59,12 @@ namespace EonaCat.HID { lock (_lock) { - if (_stream != null || _isOpen) - return; - - // Open HID device in non-blocking read/write mode + if (_stream != null || _isOpen) + { + return; + } + + // Open HID device in non-blocking read/write mode int fd = NativeMethods.open(_devicePath, NativeMethods.O_RDWR | NativeMethods.O_NONBLOCK); if (fd < 0) { @@ -262,10 +264,12 @@ namespace EonaCat.HID public async Task SendFeatureReportAsync(HidReport report) { - if (report == null) - throw new ArgumentNullException(nameof(report)); - - // Prepare full report buffer: [reportId][reportData...] + if (report == null) + { + throw new ArgumentNullException(nameof(report)); + } + + // Prepare full report buffer: [reportId][reportData...] int size = 1 + (report.Data?.Length ?? 0); byte[] buffer = new byte[size]; buffer[0] = report.ReportId; @@ -298,8 +302,11 @@ namespace EonaCat.HID } finally { - if (unmanagedBuffer != IntPtr.Zero) - Marshal.FreeHGlobal(unmanagedBuffer); + if (unmanagedBuffer != IntPtr.Zero) + { + Marshal.FreeHGlobal(unmanagedBuffer); + } + NativeMethods.close(fd); } }); @@ -342,15 +349,20 @@ namespace EonaCat.HID byte actualReportId = actualBuffer.Length > 0 ? actualBuffer[0] : (byte)0; byte[] reportData = actualBuffer.Length > 1 ? new byte[actualBuffer.Length - 1] : Array.Empty(); - if (reportData.Length > 0) - Array.Copy(actualBuffer, 1, reportData, 0, reportData.Length); - + if (reportData.Length > 0) + { + Array.Copy(actualBuffer, 1, reportData, 0, reportData.Length); + } + return new HidReport(actualReportId, reportData); } finally { - if (bufPtr != IntPtr.Zero) - Marshal.FreeHGlobal(bufPtr); + if (bufPtr != IntPtr.Zero) + { + Marshal.FreeHGlobal(bufPtr); + } + NativeMethods.close(fd); } }); diff --git a/EonaCat.HID/HidWindows.cs b/EonaCat.HID/HidWindows.cs index 5c9cc23..1aa3172 100644 --- a/EonaCat.HID/HidWindows.cs +++ b/EonaCat.HID/HidWindows.cs @@ -77,7 +77,9 @@ namespace EonaCat.HID public void Open() { if (_isOpen) + { return; + } FileAccess access = FileAccess.ReadWrite; SafeFileHandle handle = TryOpenDevice(GENERIC_READ | GENERIC_WRITE); @@ -86,14 +88,18 @@ namespace EonaCat.HID { handle = TryOpenDevice(GENERIC_READ); if (handle != null && !handle.IsInvalid) + { access = FileAccess.Read; + } } if ((handle == null || handle.IsInvalid) && Environment.Is64BitOperatingSystem) { handle = TryOpenDevice(GENERIC_WRITE); if (handle != null && !handle.IsInvalid) + { access = FileAccess.Write; + } } if (handle == null || handle.IsInvalid) @@ -110,12 +116,16 @@ namespace EonaCat.HID // HID descriptor if (!HidD_GetPreparsedData(_deviceHandle.DangerousGetHandle(), out _preparsedData)) + { throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed HidD_GetPreparsedData"); + } HIDP_CAPS caps; int capsRes = HidP_GetCaps(_preparsedData, out caps); if (capsRes != NativeMethods.HIDP_STATUS_SUCCESS) + { throw new Win32Exception(capsRes, "Failed HidP_GetCaps"); + } InputReportByteLength = caps.InputReportByteLength; OutputReportByteLength = caps.OutputReportByteLength; @@ -304,7 +314,9 @@ namespace EonaCat.HID } if (report == null) + { throw new ArgumentNullException(nameof(report)); + } // Prepare buffer with ReportId + Data var data = new byte[1 + report.Data.Length]; diff --git a/EonaCat.HID/Managers/HidManagerMac.cs b/EonaCat.HID/Managers/HidManagerMac.cs index e8cd347..f242fd5 100644 --- a/EonaCat.HID/Managers/HidManagerMac.cs +++ b/EonaCat.HID/Managers/HidManagerMac.cs @@ -107,9 +107,11 @@ namespace EonaCat.HID.Managers.Mac private void DeviceAddedCallback(IntPtr context, IntPtr result, IntPtr sender, IntPtr devicePtr) { - if (devicePtr == IntPtr.Zero) - return; - + if (devicePtr == IntPtr.Zero) + { + return; + } + try { var device = new HidMac(devicePtr); @@ -125,9 +127,11 @@ namespace EonaCat.HID.Managers.Mac private void DeviceRemovedCallback(IntPtr context, IntPtr result, IntPtr sender, IntPtr devicePtr) { - if (devicePtr == IntPtr.Zero) - return; - + if (devicePtr == IntPtr.Zero) + { + return; + } + try { var device = new HidMac(devicePtr); diff --git a/EonaCat.HID/Managers/HidManagerWindows.cs b/EonaCat.HID/Managers/HidManagerWindows.cs index f7c6e37..8b33135 100644 --- a/EonaCat.HID/Managers/HidManagerWindows.cs +++ b/EonaCat.HID/Managers/HidManagerWindows.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Runtime.InteropServices; +using System.Threading; using System.Threading.Tasks; using static EonaCat.HID.Managers.Windows.NativeMethods; @@ -20,7 +21,10 @@ namespace EonaCat.HID.Managers.Windows private const ushort HID_USAGE_PAGE_GENERIC = 0x01; private const ushort HID_USAGE_GENERIC_MOUSE = 0x02; - private static Guid GUID_DEVINTERFACE_HID = new Guid("4d1e55b2-f16f-11cf-88cb-001111000030"); + private static Guid GUID_DEVINTERFACE_HID = new Guid("4D1E55B2-F16F-11CF-88CB-001111000030"); + + private static readonly IntPtr HWND_MESSAGE = new IntPtr(-3); + private const string WINDOW_CLASS_NAME = "EonaCat_HidDeviceNotificationWindow"; private readonly object _lock = new object(); @@ -28,15 +32,15 @@ namespace EonaCat.HID.Managers.Windows private IntPtr _deviceNotificationHandle; private WndProc _windowProcDelegate; private IntPtr _messageWindowHandle; - private readonly Dictionary _knownDevices = new(); + private readonly Dictionary _knownDevices = new(); + private Thread _messageThread; public event EventHandler OnDeviceInserted; public event EventHandler OnDeviceRemoved; public HidManagerWindows() { - InitializeMessageWindow(); - RegisterForDeviceNotifications(); + // Do nothing } private void InitializeMessageWindow() @@ -46,7 +50,7 @@ namespace EonaCat.HID.Managers.Windows WNDCLASS wc = new WNDCLASS() { lpfnWndProc = _windowProcDelegate, - lpszClassName = "HidDeviceNotificationWindow_" + Guid.NewGuid(), + lpszClassName = WINDOW_CLASS_NAME, style = 0, cbClsExtra = 0, cbWndExtra = 0, @@ -61,24 +65,79 @@ namespace EonaCat.HID.Managers.Windows if (classAtom == 0) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to register window class"); - } + } + + _messageWindowHandle = CreateWindowEx( + 0, + wc.lpszClassName, + "", + 0, + 0, 0, 0, 0, + HWND_MESSAGE, + IntPtr.Zero, + wc.hInstance, + IntPtr.Zero); - _messageWindowHandle = CreateWindowEx( - 0, - wc.lpszClassName, - "", - 0, - 0, 0, 0, 0, - IntPtr.Zero, - IntPtr.Zero, - wc.hInstance, - IntPtr.Zero); if (_messageWindowHandle == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to create message-only window"); } - } + } + + public void Start() + { + _messageThread = new Thread(MessageThreadProc) + { + IsBackground = true + }; + _messageThread.SetApartmentState(ApartmentState.STA); + _messageThread.Start(); + } + public Task StartAsync() => Task.Run(Start); + + private void OnWpfMessage(object sender, dynamic e) + { + if (e.Message == WM_DEVICECHANGE) + { + WindowProc(IntPtr.Zero, e.Message, e.WParam, e.LParam); + } + } + + private void MessageThreadProc() + { + InitializeMessageWindow(); + RegisterForDeviceNotifications(); + + // Start message loop + MSG msg; + while (GetMessage(out msg, IntPtr.Zero, 0, 0)) + { + TranslateMessage(ref msg); + DispatchMessage(ref msg); + } + } + + + private void StartMessageLoop() + { + Thread thread = new Thread(() => + { + InitializeMessageWindow(); + RegisterForDeviceNotifications(); + + MSG msg; + while (GetMessage(out msg, IntPtr.Zero, 0, 0)) + { + TranslateMessage(ref msg); + DispatchMessage(ref msg); + } + }); + + thread.IsBackground = true; + thread.Start(); + } + private void RegisterForDeviceNotifications() { @@ -102,7 +161,7 @@ namespace EonaCat.HID.Managers.Windows } } - private IntPtr WindowProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam) + internal IntPtr WindowProc(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam) { if (msg == WM_DEVICECHANGE) { @@ -125,8 +184,10 @@ namespace EonaCat.HID.Managers.Windows using (var testHandle = CreateFile(devicePath, 0, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero)) { - if (testHandle.IsInvalid) - return DefWindowProc(hwnd, msg, wParam, lParam); + if (testHandle.IsInvalid) + { + return DefWindowProc(hwnd, msg, wParam, lParam); + } } var device = new HidWindows(devicePath); @@ -188,7 +249,9 @@ namespace EonaCat.HID.Managers.Windows DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (devInfo == IntPtr.Zero || devInfo == new IntPtr(-1)) + { throw new Win32Exception(Marshal.GetLastWin32Error(), "SetupDiGetClassDevs failed"); + } try { @@ -203,7 +266,9 @@ namespace EonaCat.HID.Managers.Windows { int error = Marshal.GetLastWin32Error(); if (error == ERROR_NO_MORE_ITEMS) + { break; + } throw new Win32Exception(error, "SetupDiEnumDeviceInterfaces failed"); } @@ -211,7 +276,9 @@ namespace EonaCat.HID.Managers.Windows uint requiredSize = 0; SetupDiGetDeviceInterfaceDetail(devInfo, ref iface, IntPtr.Zero, 0, ref requiredSize, IntPtr.Zero); if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER || requiredSize == 0) + { continue; + } IntPtr detailDataBuffer = Marshal.AllocHGlobal((int)requiredSize); try @@ -229,13 +296,17 @@ namespace EonaCat.HID.Managers.Windows string devicePath = Marshal.PtrToStringAuto(pDevicePathName); if (string.IsNullOrWhiteSpace(devicePath)) + { continue; + } // Try to open with zero access to ensure it’s reachable using (var testHandle = CreateFile(devicePath, 0, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero)) { if (testHandle.IsInvalid) + { continue; + } } HidWindows device; @@ -296,6 +367,35 @@ namespace EonaCat.HID.Managers.Windows } _knownDevices.Clear(); + + if (_messageThread != null && _messageThread.IsAlive) + { + // Post a quit message to end the message loop + _messageThread.Join(); + _messageThread = null; + } + + if (_windowProcDelegate != null) + { + _windowProcDelegate = null; + } + + if (_messageWindowHandle != IntPtr.Zero) + { + DestroyWindow(_messageWindowHandle); + _messageWindowHandle = IntPtr.Zero; + } + + if (_deviceNotificationHandle != IntPtr.Zero) + { + UnregisterDeviceNotification(_deviceNotificationHandle); + _deviceNotificationHandle = IntPtr.Zero; + } + + if ( _messageWindowHandle != IntPtr.Zero) + { + DestroyWindow(_messageWindowHandle); + } } } @@ -321,22 +421,21 @@ namespace EonaCat.HID.Managers.Windows public const int DBT_DEVICEREMOVECOMPLETE = 0x8004; public const int DBT_DEVTYP_DEVICEINTERFACE = 5; - [StructLayout(LayoutKind.Sequential)] - public struct WNDCLASS - { - public uint style; - [MarshalAs(UnmanagedType.FunctionPtr)] - public WndProc lpfnWndProc; - public int cbClsExtra; - public int cbWndExtra; - public IntPtr hInstance; - public IntPtr hIcon; - public IntPtr hCursor; - public IntPtr hbrBackground; - [MarshalAs(UnmanagedType.LPTStr)] - public string lpszMenuName; - [MarshalAs(UnmanagedType.LPTStr)] - public string lpszClassName; + [StructLayout(LayoutKind.Sequential)] + public struct WNDCLASS + { + public uint style; + public WndProc lpfnWndProc; + public int cbClsExtra; + public int cbWndExtra; + public IntPtr hInstance; + public IntPtr hIcon; + public IntPtr hCursor; + public IntPtr hbrBackground; + [MarshalAs(UnmanagedType.LPTStr)] + public string lpszMenuName; + [MarshalAs(UnmanagedType.LPTStr)] + public string lpszClassName; } [StructLayout(LayoutKind.Sequential)] @@ -373,9 +472,20 @@ namespace EonaCat.HID.Managers.Windows [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string DevicePath; + } + + [StructLayout(LayoutKind.Sequential)] + public struct MSG + { + public IntPtr hwnd; + public uint message; + public IntPtr wParam; + public IntPtr lParam; + public uint time; + public int pt_x; + public int pt_y; } - // Declare delegate for WndProc public delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); @@ -397,9 +507,6 @@ namespace EonaCat.HID.Managers.Windows [DllImport("user32.dll")] public static extern bool DestroyWindow(IntPtr hWnd); - [DllImport("kernel32.dll", CharSet = CharSet.Auto)] - public static extern IntPtr GetModuleHandle(string lpModuleName); - [DllImport("user32.dll")] public static extern IntPtr DefWindowProc(IntPtr hwnd, uint uMsg, IntPtr wParam, IntPtr lParam); @@ -454,7 +561,22 @@ namespace EonaCat.HID.Managers.Windows IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, - IntPtr hTemplateFile); + IntPtr hTemplateFile); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax); + + [DllImport("user32.dll")] + public static extern bool TranslateMessage([In] ref MSG lpMsg); + + [DllImport("user32.dll")] + public static extern IntPtr DispatchMessage([In] ref MSG lpMsg); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr GetModuleHandle(string lpModuleName); + + [DllImport("user32.dll", SetLastError = true)] + public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, int Flags); // HID APIs [DllImport("hid.dll", SetLastError = true)]