因为手上的其中一个项目需要监视 USB 或串口,网上可以搜到很多基于 Windows 通知机制以及 PyQt4 的资料。但在此项目基于的 PyQt5 中,事件函数 winEvent 已经被 nativeEvent 所取代。为此我基于网络上的文档,在 PyQt 5.12 上重新编写了串口监视模块。

遇到的坑

通知的 lParam 参数会包含变化的端口数据,需要转成 DBT 结构体才可以正常读出。DEV_BROADCAST_HDR 其实是一个通用结构体,需要读取设备类型才能判断要用什么具体的结构体来转换。我之前看一些文章里串口也是用的 DEV_BROADCAST_DEVICEINTERFACE,结果无法正确读取路径,必须要用对应的 DEV_BROADCAST_PORT 才能读出变更端口的名称,注意一定要对应!

DBT 结构体需要参考微软 API 文档进行编写: https://docs.microsoft.com/en-us/windows/desktop/api/dbt/ns-dbt-dev_broadcast_port_w

在 PyQt 中,只有 QWidget 或继承 QWidget 的类才拥有句柄,并且拥有 nativeEventcloseEvent 等函数的事件机制,而 QObject 是没有的,这就是为什么我的模块用的是 QWidget

另外,如果你想直接在主窗口使用,而不是像我这样包成一个类,可以不用注册与反注册通知,因为在最顶层的窗口 PyQt 会默认注册这项通知。

类源码

如何使用

在程序中基于类定义一个对象,并连接 device_removeddevice_discovered 信号至对应的槽函数即可,当设备变化时将会传送端口的友好名字(例如 COM1)过来。

Hintay

Hintay

一个懒人

评论

表情 贴图 加粗 删除线 居中 斜体 下划线 引用 代码
:wink: :roll: :oops: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-? :* :) :( :!: 8-O 8* 8) /:tangled /:spoof05 /:spoof04 /:spoof03 /:spoof02 /:spoof01 /:spoof /:rwt /:rose /:neartears /:like /:lac /:impotence /:hematemesis /:harass /:fade /:doge /:cute /:chin /:candle /:bye /:beautiful /:P-( /:>-| /::| /::Z /::X /::T /::Q /::P /::O /::D /::@ /::> /:::D /::-| /::( /::$ /:--b /:,@P