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

2024-03-26

我的主要目标是纯粹使用以下方法实现正确的消息循环P/Invoke http://en.wikipedia.org/wiki/Platform_Invocation_Services能够处理 USB HID 事件的调用。当然,它的功能应该与以下代码相同,可以很好地工作Windows 窗体 http://en.wikipedia.org/wiki/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.

尝试直接在消息循环内处理所有消息将非常困难,这就是创建窗口过程的原因。并且不要打电话TranslateMessage or DispatchMessage对于您选择直接处理的任何消息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实现 Win32 消息循环并使用 P/Invoke 创建 Window 对象 的相关文章

  • 为什么两个不同的 Base64 字符串的转换会返回相等的字节数组?

    我想知道为什么从 base64 字符串转换会为不同的字符串返回相同的字节数组 const string s1 dg const string s2 dq byte a1 Convert FromBase64String s1 byte a2
  • 按成员序列化

    我已经实现了template
  • 秒表有最长运行时间吗?

    多久可以Stopwatch在 NET 中运行 如果达到该限制 它会回绕到负数还是从 0 重新开始 Stopwatch Elapsed返回一个TimeSpan From MSDN https learn microsoft com en us
  • 在哪里可以找到列出 SSE 内在函数操作的官方参考资料?

    是否有官方参考列出了 GCC 的 SSE 内部函数的操作 即 头文件中的函数 除了 Intel 的 vol 2 PDF 手册外 还有一个在线内在指南 https www intel com content www us en docs in
  • ASP.NET MVC:这个业务逻辑应该放在哪里?

    我正在开发我的第一个真正的 MVC 应用程序 并尝试遵循一般的 OOP 最佳实践 我正在将控制器中的一些简单业务逻辑重构到我的域模型中 我最近一直在阅读一些内容 很明显我应该将逻辑放在域模型实体类中的某个位置 以避免出现 贫血域模型 反模式
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 如何在整个 ASP .NET MVC 应用程序中需要授权

    我创建的应用程序中 除了启用登录的操作之外的每个操作都应该超出未登录用户的限制 我应该添加 Authorize 每个班级标题前的注释 像这儿 namespace WebApplication2 Controllers Authorize p
  • 如何在 C 中调用采用匿名结构的函数?

    如何在 C 中调用采用匿名结构的函数 比如这个函数 void func struct int x p printf i n p x 当提供原型的函数声明在范围内时 调用该函数的参数必须具有与原型中声明的类型兼容的类型 其中 兼容 具有标准定
  • 链接器错误:已定义

    我尝试在 Microsoft Visual Studio 2012 中编译我的 Visual C 项目 使用 MFC 但出现以下错误 error LNK2005 void cdecl operator new unsigned int 2
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co
  • C++ 标准是否指定了编译器的 STL 实现细节?

    在写答案时this https stackoverflow com questions 30909296 can you put a pimpl class inside a vector我遇到了一个有趣的情况 这个问题演示了这样一种情况

随机推荐

  • Objective C - 获取今天(明天)的第二天

    如何检查某个日期是否本质上是 明天 我不想在像今天这样的日期上添加时间或任何内容 因为如果今天已经22 59 添加太多会延续到后天 添加太少则时间到了12 00会错过明天 我怎样才能检查两个NSDate并确保其中一个相当于另一个的明天 Us
  • Sklearn ROC AUC 分数:ValueError:y 应该是一个一维数组,而是一个形状为 (15, 2) 的数组

    我有这个带有目标的数据集LULUS 这是一个不平衡数据集 我正在尝试打印roc auc如果我可以对数据的每个折叠进行评分 但在每个折叠中 不知怎的 它总是会引发错误说ValueError y should be a 1d array got
  • 断点指出“objc_autoreleaseNoPool”

    因此 我正在调试一个应用程序 为其应用程序发布做准备 并且我为 所有异常 启用了通用断点 从那时起 每次我运行该应用程序时 控制台都会打印 捕获点 2 抛出 挂起的断点 1 objc exception throw 已解决 objc 117
  • Laravel 具有不同的会话生命周期

    问 如何在 Laravel 5 中创建不同生命周期的会话 这个问题不是重复的这个问题 https stackoverflow com q 40258339 1474817 我不想将其用于任何类型的登录或注册 我只想将其存储 5 分钟 因为获
  • 如何像编译器一样获取每个虚函数索引?

    是否有一些插件或工具可以读取 h 文件 或简单地修改 Intellisense 本身 并吐出每个函数及其虚拟函数表索引 有一种模式我还没有弄清楚与多态性有关 当你开始有 5 个或更多的类相互派生时 它就会变得困难 5 倍 但无论如何 MSV
  • IntelliJ IDEA:如何修复损坏的字体显示?

    无法阅读该语言 怎么设置成英文呢 The issue is not with the language but with some broken font mapping on your system The workaround is t
  • Node.js + Azure SQL 数据库

    我正在挣扎微软的node js sql客户端 https github com WindowsAzure node sqlserver 我已经安装了它 使用 github 页面上的指南没有任何错误 并且一切在本地运行完美 但是当我使用 gi
  • 如何根据 HTML 从统计页面中提取玩家信息?

    我正在尝试使用 selenium 抓取网站的一些信息 下面是该网站的链接http www ultimatetennisstatistics com playerProfile playerId 4742 http www ultimatet
  • C语言中的宏(#define)

    我正在阅读hoard内存分配器的源代码 在gnuwrapper cpp文件中 有以下代码 define CUSTOM MALLOC x CUSTOM PREFIX malloc x 是什么意思CUSTOM PREFIX malloc x i
  • MPAndroidChart 条形图 - 如何对组之间具有随机 x 轴间隔的条形进行分组?

    我想制作一个条形图 其中每个数据点将 3 个不同的数据集分组在一起 如下所示 但是 我无法使用库提供的功能将条形图分组在一起groupBars方法 因为无论我为条目设置什么 x 值 它都会根据我在其参数中指定的间隔对条形进行分组 例如 如果
  • 镜头:新型变焦

    我有兴趣获得zooming我的 monad 变压器堆栈的功能定义如下 newtype Awesome a Awesome StateT AwesomeState ExceptT B ByteString IO a deriving Func
  • Python 将列表转换为集合,大 O

    感谢您的帮助 words Big list of words words set set words 当 n len words 时 我很难确定 set words 的复杂性是多少 是 O n 因为它在列表的所有项目上移动 还是 O l n
  • 如何让odeint成功?

    我是 python 初学者 目前使用 scipy 的odeint计算耦合的 ODE 系统 但是 当我运行时 python shell 总是告诉我 gt gt gt Excess work done on this call perhaps
  • 在 PHP 中将十六进制转换为图像?

    我正在开发通过以下方式与服务器通信的移动应用程序PHP Webservice 这是我第一次使用 PHP 我设法将数据上传到数据库 现在我需要发送图像以将其存储在 ftp 服务器中 为此我转换了image gt hex并从我的应用程序发送 服
  • 如何在安装时强制 Chrome 扩展上的键盘快捷键

    我正在尝试实现一个使用键盘快捷键触发事件的 Chrome 扩展 快捷方式在这里声明 commands sample suggested key default Ctrl I windows Ctrl I description Refres
  • emacs autoloaded 中保证自动加载功能的机制是什么

    我知道所有标有 Autoload 行的函数都将是自动加载函数 但问题是执行此 自动加载函数 的底层机制是什么 还有为什么当从 elpa 安装软件包时 会出现一个名为 XXX autoload elc 的编译文件 当您安装 Elpa 软件包时
  • Php变量存储字符串时的大小限制是多少?

    情况是这样的 我有一个 2Gb 的转储文件 名为myDB sql 它是一个转储文件 可删除现有数据库并创建一个带有视图和触发器的新数据库 所以我有字符串myDB OLD分布在许多行代码中 我想将这些字符串的出现次数更改为myDB NEW 我
  • Google reCAPTCHA、405 错误和 CORS 问题

    我正在使用 AngularJS 并尝试使用 Google 的 reCAPTCHA 我正在使用 显式呈现 reCAPTCHA 小部件 在我的网页上显示 reCAPTCHA 的方法 HTML 代码
  • 如何使用 ListView 呈现具有多个行跨列的数据表

    我需要在 html 表中显示数据库中的数据 我目前正在使用 ListView 控件 我希望最终的 HTML 表呈现如下所示的内容 其中某些行有一个rowspan属性大于一 原因是有些字段有几行信息 但对应同一个逻辑条目 例如 data da
  • 实现 Win32 消息循环并使用 P/Invoke 创建 Window 对象

    我的主要目标是纯粹使用以下方法实现正确的消息循环P Invoke http en wikipedia org wiki Platform Invocation Services能够处理 USB HID 事件的调用 当然 它的功能应该与以下代