PyQt4实现USB设备插入到弹出的检测(Windows)
2012-02-11 17:53
696 查看
直没怎么看过 QextSerialPort 中windows下枚举串口的具体实现(原因?对win32api不了解,看不懂啊_)
经过一段时间的学习,对QextSerialPort总算理清了一些,于是,就可以用python实现枚举串口了,也可以检测串口的载入与移除了。
不过呢?除了"usb转的串口"容易被移除外,想移除串口还真不太容易。所以可能没什么实际作用。于是呢?
写到最后,还是改主意了。用它来实现USB设备的插入与移除吧.
先记录一下程序编写中遇到的困难
一开始就在它上面遇到了问题,因为按照win32的头文件给结构体,dbcc_name 是长度为1的数组。
我也将其定义为长度1的数组 ctypes.c_wchar*1
然后 RegisterDeviceNotification 调用不成功,通过FormatError得到“参数错误”
解决方案,添加 _pack_ = 1后错误消失
然而到最后,仅仅这样还不行,因为无法通过 dbcc_name 得到需要的字符串(因为它长度是1) 所以最终采用的方案如上
对 PyQt4 不熟,所以想当然认为其余Qt4提供的签名应该一样了:
结果运行时老是警告:参数个数不对。
原来在PyQt4里,真正的函数签名应该是:
注:PySide 尚未提供该方法,所以本程序无法在PySide下运行:
源代码:
经过一段时间的学习,对QextSerialPort总算理清了一些,于是,就可以用python实现枚举串口了,也可以检测串口的载入与移除了。
不过呢?除了"usb转的串口"容易被移除外,想移除串口还真不太容易。所以可能没什么实际作用。于是呢?
写到最后,还是改主意了。用它来实现USB设备的插入与移除吧.
先记录一下程序编写中遇到的困难
class DEV_BROADCAST_DEVICEINTERFACE(ctypes.Structure): _pack_ = 1 _fields_ = [("dbcc_size", wintypes.DWORD), ("dbcc_devicetype", wintypes.DWORD), ("dbcc_reserved", wintypes.DWORD), ("dbcc_classguid", GUID), ("dbcc_name", ctypes.c_wchar*260)]
一开始就在它上面遇到了问题,因为按照win32的头文件给结构体,dbcc_name 是长度为1的数组。
我也将其定义为长度1的数组 ctypes.c_wchar*1
然后 RegisterDeviceNotification 调用不成功,通过FormatError得到“参数错误”
解决方案,添加 _pack_ = 1后错误消失
然而到最后,仅仅这样还不行,因为无法通过 dbcc_name 得到需要的字符串(因为它长度是1) 所以最终采用的方案如上
对 PyQt4 不熟,所以想当然认为其余Qt4提供的签名应该一样了:
bool QWidget::winEvent ( MSG * message, long * result )
结果运行时老是警告:参数个数不对。
原来在PyQt4里,真正的函数签名应该是:
def winEvent(self, msg): return False,id(msg)
注:PySide 尚未提供该方法,所以本程序无法在PySide下运行:
源代码:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
'''
Copyright (C) 2010 dbzhang800
All rights reserved.
'''
import sys
import ctypes
import ctypes.wintypes as wintypes
from PyQt4.QtCore import *
from PyQt4.QtGui import *
NULL = 0
INVALID_HANDLE_VALUE = -1
DBT_DEVTYP_DEVICEINTERFACE = 5
DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000
DBT_DEVICEREMOVECOMPLETE = 0x8004
DBT_DEVICEARRIVAL = 0x8000
WM_DEVICECHANGE = 0x0219
user32 = ctypes.windll.user32
RegisterDeviceNotification = user32.RegisterDeviceNotificationW
UnregisterDeviceNotification = user32.UnregisterDeviceNotification
class GUID(ctypes.Structure):
_pack_ = 1
_fields_ = [("Data1", ctypes.c_ulong),
("Data2", ctypes.c_ushort),
("Data3", ctypes.c_ushort),
("Data4", ctypes.c_ubyte * 8)]
class DEV_BROADCAST_DEVICEINTERFACE(ctypes.Structure): _pack_ = 1 _fields_ = [("dbcc_size", wintypes.DWORD), ("dbcc_devicetype", wintypes.DWORD), ("dbcc_reserved", wintypes.DWORD), ("dbcc_classguid", GUID), ("dbcc_name", ctypes.c_wchar*260)]
class DEV_BROADCAST_HDR(ctypes.Structure):
_fields_ = [("dbch_size", wintypes.DWORD),
("dbch_devicetype", wintypes.DWORD),
("dbch_reserved", wintypes.DWORD)]
GUID_DEVCLASS_PORTS = GUID(0x4D36E978, 0xE325, 0x11CE,
(ctypes.c_ubyte*8)(0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18))
GUID_DEVINTERFACE_USB_DEVICE = GUID(0xA5DCBF10L, 0x6530,0x11D2,
(ctypes.c_ubyte*8)(0x90, 0x1F, 0x00,0xC0, 0x4F, 0xB9, 0x51, 0xED))
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.resize(QSize(600, 320))
self.setWindowTitle("Device Notify")
self.setupNotification()
vbox = QVBoxLayout(self)
vbox.addWidget(QLabel("Log window:", self))
self.logEdit = QPlainTextEdit(self)
vbox.addWidget(self.logEdit)
self.setLayout(vbox)
def setupNotification(self):
dbh = DEV_BROADCAST_DEVICEINTERFACE()
dbh.dbcc_size = ctypes.sizeof(DEV_BROADCAST_DEVICEINTERFACE)
dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE
dbh.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE #GUID_DEVCLASS_PORTS
self.hNofity = RegisterDeviceNotification(int(self.winId()),
ctypes.byref(dbh),
DEVICE_NOTIFY_WINDOW_HANDLE)
if self.hNofity == NULL:
print ctypes.FormatError(), int(self.winId())
print "RegisterDeviceNotification failed"
def closeEvent(self, evt):
if self.hNofity:
UnregisterDeviceNotification(self.hNofity)
super(Window, self).closeEvent(evt)
def winEvent(self, message):
if message.message == WM_DEVICECHANGE:
self.onDeviceChanged(message.wParam, message.lParam)
return True, id(message)
return False, id(message)
def onDeviceChanged(self, wParam, lParam):
if DBT_DEVICEARRIVAL == wParam:
self.logEdit.appendHtml("<font color=blue>Device Arrival:</font>")
elif DBT_DEVICEREMOVECOMPLETE == wParam:
self.logEdit.appendHtml("<font color=red>Device Removed:</font>")
if (DBT_DEVICEARRIVAL == wParam or DBT_DEVICEREMOVECOMPLETE == wParam):
dbh = DEV_BROADCAST_HDR.from_address(lParam)
if dbh.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE:
dbd = DEV_BROADCAST_DEVICEINTERFACE.from_address(lParam)
self.logEdit.appendPlainText(dbd.dbcc_name)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())
相关文章推荐
- USB设备的插入检测
- 如何实现WinCE系统中USB设备自动检测
- Android有两种方法检测USB设备插入
- USB设备插入/拔出时重要的windows消息值
- 一个很有用的检测USB设备插入拔出的对象
- windows下弹出指定USB设备的小程序
- USB设备的插入检测
- Windows 下获取USB设备信息的通用浏览器插件实现
- C#实现USB插入检测,移除
- USB学习系列之二——USB设备的插入检测
- Android插入USB设备,自动弹出提示运行apk
- USB入门系列之五 —— USB设备的插入检测机制[图]
- Windows上USB设备检测
- USB入门系列之五 —— USB设备的插入检测机制
- 一个很有用的检测USB设备插入拔出的对象(from Torry's Dephi Pages)
- 硬件检测:安装、停用、usb设备检查 和c#实现
- 两种检测USB设备插入和移除的方法(Ver 2)
- 安卓检测USB设备插入之后回调用户代码的小框架编写
- USB主机是如何检测到设备的插入的呢?
- Windows中USB设备插入的拔出和所产生的消息值