实现Win32消息循环并使用P

实现Win32消息循环并使用P

本文介绍了实现Win32消息循环并使用P/Invoke创建Window对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的主要目标是纯粹通过 P/Invoke 调用来实现适当的消息循环能够处理USB HID事件.绝对其功能应与在 Windows窗体中正常运行的以下代码相同.此NativeWindow后代接收事件:

My main goal is to implement a proper message loop purely with P/Invoke calls that is able to handle USB HID events. Definitely its functionality should be identical with the following code that works well in Windows Forms. This NativeWindow descendant receives the 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 implementing the event loop is rather easy:

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类的实现对我来说太复杂了.

But I have no idea how the underlying Window object should be created. The implementation of the NativeWindow class seems too complex 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;
}

推荐答案

这是一个功能很弱的事件循环.考虑使用类似MsgWaitForMultipleObjectsEx的方式代替GetMessage.

That's an very under-powered event loop. Consider using something like MsgWaitForMultipleObjectsEx instead of GetMessage.

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

Anyway, creating a window requires you to first register a window class (RegisterClassEx) and then create the window (CreateWindow). Neither one is particularly difficult. And instead of using base.WndProc(), you'll need to call DefWindowProc.

试图直接在消息循环内处理所有消息将非常困难,这就是创建窗口过程的原因.而且,对于选择直接处理的任何消息,请勿致电TranslateMessageDispatchMessage.

Trying to handle all messages directly inside the message loop is going to be overly difficult, that's why window procedures were created. And don't call TranslateMessage or DispatchMessage for any message you choose to process directly.

这篇关于实现Win32消息循环并使用P/Invoke创建Window对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 05:54