实现一个Win32消息循环和创建窗口对象的P / Invoke [英] Implementing a Win32 message loop and creating Window object with P/Invoke

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

问题描述

我的主要目标是纯粹的实现适当的消息循环使用的P / Invoke调用,能够处理USB HID事件。肯定它的功能应该是相同的以下code,在WinForms.NET效果很好。由此NativeWindow descandent接收事件:

 公共类Win32EventHandler:NativeWindow的
{
    公共const int的WM_DEVICECHANGE = 0x0219;

    公共Win32EventHandler()
    {
        this.CreateHandle(新的CreateParams());
    }

    保护覆盖无效OnHandleChange()
    {
        base.OnHandleChange();

        IntPtr的处理= UsbHelper.RegisterForUsbEvents(this.Handle);
    }

    保护覆盖无效的WndProc(参考消息M)
    {
        如果(m.Msg == WM_DEVICECHANGE)
        {
            //处理事件
        }

        base.WndProc(REF米);
    }
}
 

...搭载这一事件循环:

  Win32EventHandler处理器=新Win32EventHandler();

VAR上下文=新的ApplicationContext();
Application.Run(上下文);

//其他线程调用:
// context.ExitThread()
 

我发现执行事件循环是相当容易的:

 ,而(真)
{
    RES = Win32.GetMessage(出味精,IntPtr.Zero,0,0);

    如果(RES == 0)
    {
        打破;
    }

    Win32.TranslateMessage(REF MSG);
    Win32.DispatchMessage(REF MSG);

    如果(msg.message == WM_DEVICECHANGE)
    {
        //处理事件
    }
}
 

不过,我不知道如何底层的Window对象应创建。 NativeWindow类的实现似乎太复杂了我。

更新: 这是我目前的解决方案:

 公共无效CustomLoop()
{
    字符串clsName =类;
    字符串wndName =窗口;

    Win32.WNDCLASSEX WNDCLASSEX =新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味精;
    为sbyte解析度= 0;

    而(真)
    {
        RES = Win32.GetMessage(出味精,IntPtr.Zero,0,0);

        如果(RES == 0)
        {
            打破;
        }

        如果(msg.message == WM.DEVICECHANGE)
        {
            //处理事件(不火)
        }
        其他
        {
            Win32.TranslateMessage(REF MSG);
            Win32.DispatchMessage(REF MSG);
        }

    }

    Win32.DestroyWindow(windowHandle);
    Win32.UnregisterClass(clsName,IntPtr.Zero);
}

[AllowReversePInvokeCalls]
私有的IntPtr的WndProc(IntPtr的的HWND,WM味精,IntPtr的wParam中,IntPtr的lParam的)
{
    开关(MSG)
    {
        案例WM.DEVICECHANGE:
            //处理事件(火灾
            打破;
        默认:
            返回Win32.DefWindowProc(HWND,味精,的wParam,lParam的);
    }

    返回IntPtr.Zero;
}
 

解决方案

这是一个非常在供电事件循环。考虑使用,而不是的GetMessage 类似 MsgWaitForMultipleObjectsEx

总之,创建一个窗口要求您先注册一个窗口类( RegisterClassEx ),然后创建窗口(CreateWindow的 C>)。没有一个是特别困难的。而不是使用 base.WndProc()和,你将需要调用给DefWindowProc

试图直接处理所有邮件里面的消息循环将是太困难,这就是为什么创建窗口过程。不要叫的TranslateMessage 在DispatchMessage 供您选择直接处理的任何消息。

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 WinForms.NET. This NativeWindow descandent 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
    }
}

But I have no idea how the underlying Window object should be created. The implementation of the NativeWindow class seems too complex for me.

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

解决方案

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

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.

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆