gpt4 book ai didi

c# - 实现 Win32 消息循环并使用 P/Invoke 创建 Window 对象

转载 作者:太空狗 更新时间:2023-10-30 01:24:32 31 4
gpt4 key购买 nike

我的主要目标是纯粹使用 P/Invoke 实现适当的消息循环能够处理 USB HID 事件的调用。绝对它的功能应该与以下在 Windows Forms 中运行良好的代码相同.此 NativeWindow 后代接收事件:

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;
}

最佳答案

这是一个非常低效的事件循环。考虑使用 MsgWaitForMultipleObjectsEx 而不是 GetMessage

无论如何,创建一个窗口需要先注册一个窗口类(RegisterClassEx),然后再创建窗口(CreateWindow)。两者都不是特别困难。而不是使用 base.WndProc(),您需要调用 DefWindowProc

试图直接在消息循环内处理所有消息将过于困难,这就是创建窗口过程的原因。并且不要为您选择直接处理的任何消息调用 TranslateMessageDispatchMessage

关于c# - 实现 Win32 消息循环并使用 P/Invoke 创建 Window 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8980873/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com