PyQt5 使用windows系统消息

PyQt5 使用windows系统消息 识别设备插拔

关键字: python, PyQt5, nativeEvent, WM_DEVICECHANGE, winEvent

以下代码已经过精简,去除无关部分,可直接运行,运行环境为python3.8.3 64bit PyQt5.14.2 64bit

    import sys
    from PyQt5.QtWidgets import QMainWindow, QApplication
    from ctypes.wintypes import MSG
    
    class MainWindow(QMainWindow):
    
        def __init__(self):
            QMainWindow.__init__(self)
            
        def nativeEvent(self, eventType, msg):
            message = MSG.from_address(msg.__int__())
            if message.message == 0x219:  # WM_DEVICECHANGE
                if message.wParam == 0x8000:  # DBT_DEVICEARRIVAL
                    print("in")
                elif message.wParam == 0x8004:  # DBT_DEVICEREMOVECOMPLETE
                    print("out")
                elif message.wParam == 0x0007:  # DBT_DEVNODE_CHANGED
                    print("node")
            return False, 0
    
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

运行时,会有一个很小的界面,界面里什么都没有。插拔设备会在解释器的终端里输出。

更新

这篇文章在PyQt5.11.3的时候写的。在PyQt5.14.2出错了。因为nativeEvent的返回值问题。
之前并不理解返回值的意义,瞎填的果然会出错。

我看PyQt的文档
https://www.riverbankcomputing.com/static/Docs/PyQt5/incompatibilities.html
这个问题应该是5.12引入的,是一个关于数据类型转换可能导致溢出的问题。以前是忽略的。那这是一个漏洞,确实是要修复的。

在PyQt的文档里关于nativeEvent是这样的
https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qwidget.html
nativeEvent(Union[QByteArray, bytes, bytearray], sip.voidptr) → (bool, int)
返回值是一个bool和int

先说bool
True 代表我处理了消息,不需要Qt处理。False 代表我不处理消息,需要Qt处理。根据情况填写。

再说int
之前我是返回msg,它是一个sip.voidptr。作为返回值。编译器会去调他的__int__()函数返回int类型。
但是由于实际数据位宽问题,PyQt不允许这么干了。不过即便PyQt让,这种做法也是错误的。因为可以确定的是这个返回值返回的就不应该是系统消息。

有不少人是直接填0的。这么做有可能是正确的。
Qt4 Qt5的文档我都查了一下,也没有弄明白这个int返回值到底是干嘛的。
https://doc.qt.io/qt-5/qwidget.html#nativeEvent
https://doc-snapshots.qt.io/4.8/qwidget.html#winEvent
由于Qt5标注了这个result是LRESULT,所以我猜它应该是message.lParam。
但是直接返回这个是失败的。因为message.lParam是一个c_long,而result是int。

有一个demo用这个返回值传递参数
https://github.com/PyQt5/PyQt/blob/63c6376358acb1863313fb5593097e6e0210cad6/Demo/NativeEvent.py
我觉的这个作者应该是很了解nativeEvent的用法。不过他用的库我没有,也无法验证。

以下链接是ctypes.wintypes.MSG的结构
http://epydoc.sourceforge.net/stdlib/ctypes.wintypes.MSG-class.html
不知道为啥python官网找不到

最终我并没有搞清楚这个int返回值是干什么用的,如果你清楚,请回复我,非常感谢。
如果对以上有什么疑问也请回复我。

你可能感兴趣的:(pyqt5)