Implementing a Win32 Message Loop and Creating a Window Object Using P / Invoke

My main goal is to implement the correct message loop using P / Invoke calls capable of handling USB HID events. Definitely its functionality should be identical to the following code, which works well in Windows Forms . This descendant of NativeWindow receives events:

public class Win32EventHandler : NativeWindow { public const int WM_DEVICECHANGE = 0x0219; public Win32EventHandler() { this.CreateHandle(new CreateParams()); } protected override void OnHandleChange() { base.OnHandleChange(); IntPtr handle = UsbHelper.RegisterForUsbEvents(this.Handle); } protected override void WndProc(ref Message m) { if (m.Msg == WM_DEVICECHANGE) { // Handle event } base.WndProc(ref m); } } 

... powered by this event loop:

 Win32EventHandler handler = new Win32EventHandler(); var context = new ApplicationContext(); Application.Run(context); // Other thread calls: // context.ExitThread() 

I found out that the implementation of the event loop is quite simple:

 while (true) { res = Win32.GetMessage(out msg, IntPtr.Zero, 0, 0); if (res == 0) { break; } Win32.TranslateMessage(ref msg); Win32.DispatchMessage(ref msg); if (msg.message == WM_DEVICECHANGE) { // Handle event } } 

But I have no idea how to create a basic Window object. Implementing the NativeWindow class seems too complicated for me.

This is my solution at the moment:

 public void CustomLoop() { string clsName = "Class"; string wndName = "Window"; Win32.WNDCLASSEX wndClassEx = new Win32.WNDCLASSEX(); wndClassEx.cbSize = (uint)Marshal.SizeOf(wndClassEx); wndClassEx.lpszClassName = clsName; wndClassEx.lpfnWndProc = WndProc; Win32.RegisterClassEx(ref wndClassEx); IntPtr windowHandle = Win32.CreateWindowEx(0, clsName, wndName, 0, 0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); IntPtr usbEventHandle = UsbHelper.RegisterForUsbEvents(windowHandle); Win32.MSG msg; sbyte res = 0; while (true) { res = Win32.GetMessage(out msg, IntPtr.Zero, 0, 0); if (res == 0) { break; } if (msg.message == WM.DEVICECHANGE) { // Handle event (does not fire) } else { Win32.TranslateMessage(ref msg); Win32.DispatchMessage(ref msg); } } Win32.DestroyWindow(windowHandle); Win32.UnregisterClass(clsName, IntPtr.Zero); } [AllowReversePInvokeCalls] private IntPtr WndProc(IntPtr hWnd, WM msg, IntPtr wParam, IntPtr lParam) { switch (msg) { case WM.DEVICECHANGE: // Handle event (fires) break; default: return Win32.DefWindowProc(hWnd, msg, wParam, lParam); } return IntPtr.Zero; } 
+4
source share
2 answers

This is a very slow cycle of events. Think use MsgWaitForMultipleObjectsEx something like GetMessage .

In any case, to create a window, you must first register the window class ( RegisterClassEx ), and then create the window ( CreateWindow ). None of them are particularly complex. Instead of using base.WndProc() you need to call DefWindowProc .

Trying to process all messages directly inside the message loop will be too complex, so window procedures were created. And do not call TranslateMessage or DispatchMessage for any message that you want to process directly.

+4
source

You can check how this guy discovers USB devices: USB library for detecting USB devices

0
source

Source: https://habr.com/ru/post/1392585/


All Articles