我的主要目標是純粹使用能夠處理USB HID事件的P/Invoke調用實現適當的消息循環。當然,它的功能應該與以下代碼相同,在Windows Forms中運行良好。由此NativeWindow後裔接收事件:實現Win32消息循環並使用P/Invoke創建Window對象
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);
}
}
...搭載此事件循環:
Win32EventHandler handler = new Win32EventHandler();
var context = new ApplicationContext();
Application.Run(context);
// Other thread calls:
// context.ExitThread()
我發現執行事件循環是相當容易:
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
}
}
但我不知道如何創建底層Window對象。 NativeWindow類的實現對我來說似乎太複雜了。
這是我的解決方案的時刻:
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;
}
出於好奇,如果你有工作代碼,你爲什麼要改寫它不同的方式? –
我想用P/Invoke在Silverlight 5中捕獲這些事件。有一個很好的理由,它完全缺乏Win32特定的東西。 – tamasf
你從pinvoke.net獲得p/invoke聲明? –