【问题标题】:Detected new usb device connected/disconnected on Qt在 Qt 上检测到新的 USB 设备连接/断开连接
【发布时间】:2016-07-22 14:14:35
【问题描述】:

我希望在连接或断开新 USB 设备时收到通知(设备隐藏)。当有 USB 设备更改时,我已成功收到通知,但我不知道设备是连接还是断开连接。 我收到的消息(连接或断开 USB 时)是相同的: 消息:537(VM_DEVICECHANGE) w参数:7 lParam : 0

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QAbstractEventDispatcher>
#include <QAbstractNativeEventFilter>
#include <QDebug>
#include <windows.h>
#include <dbt.h>
#include <QObject>

class MyNativeEventFilter : public QAbstractNativeEventFilter {
public :
    virtual bool nativeEventFilter( const QByteArray &eventType, void *message, long *result )
    Q_DECL_OVERRIDE
    {
        if (eventType == "windows_generic_MSG")
        {
          MSG *msg = static_cast<MSG *>(message);
          static int i = 0;

              msg = (MSG*)message;
                  qDebug() << "message: " << msg->message << " wParam: " << msg->wParam
                      << " lParam: " << msg->lParam;
              if (msg->message == WM_DEVICECHANGE)
              {
                  qDebug() << "WM_DEVICECHANGE";
              }
            }
        return false;
    }
};

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    MyNativeEventFilter myEventfilter;
    app.eventDispatcher()->installNativeEventFilter(&myEventfilter);
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

【问题讨论】:

  • Offtopic:为什么需要自定义窗口?只需使用qApp-&gt;eventDispatcher()-&gt;installNativeEventFilter( yourEventFilter);yourEventFilter 应该是 QAbstractNativeEventFilter 的孩子
  • @DmitrySazonov 谢谢你的技巧,但我总是遇到同样的“问题”(我已经编辑了我的帖子)

标签: windows qt events notifications usb


【解决方案1】:

WM_DEVICECHANGE message 并不能真正告诉您设备是已连接还是已断开连接。收到该消息后,您的应用程序应使用 SetupAPI 查看所有已连接的 USB 设备并采取适当的措施。

【讨论】:

  • 当您收到WM_DEVICECHANGE 消息时,您可以检查wParamDBT_DEVICEARRIVALDBT_DEVICEREMOVECOMPLETE
  • 但是 OP 正在获取 DBT_DEVNODES_CHANGED 所以这两个检查都会失败。
  • wParam 等于 7 (DBT_DEVNODES_CHANGED.)。如果我理解它是不可能很容易知道它是连接还是删除。我使用一个API来查看隐藏设备(hidapi),我认为最好是使用它来知道它是连接还是删除
【解决方案2】:

这是我在我的一个项目中用于获取 USB 连接/断开通知的方法:

/** deviceeventfilter.h **/
class DeviceEventFilter: public QObject, public QAbstractNativeEventFilter
{
    Q_OBJECT
public:
    explicit DeviceEventFilter(QObject *parent = 0);
    virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);

signals:
    void newUSBDevice();
    void lostUSBDevice();

public slots:
    void registerEvent(QWindow *window);
};

/** deviceeventfilter.cpp **/
DeviceEventFilter::DeviceEventFilter(QObject *parent) :
    QObject(parent)
{

}

bool DeviceEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
    Q_UNUSED(eventType);
    Q_UNUSED(result);
#ifdef Q_OS_WIN32
    MSG *msg = (MSG *)message;
    if( WM_DEVICECHANGE == msg->message && DBT_DEVICEARRIVAL == msg->wParam )
    {
        qDebug("USB arrival detected!");
        emit newUSBDevice();
    }
    else if( WM_DEVICECHANGE == msg->message && DBT_DEVICEREMOVECOMPLETE == msg->wParam )
    {
        qDebug("USB departure detected!");
        emit lostUSBDevice();
    }
#endif
    // Return false so that the event is propagated
    return false;
}


void DeviceEventFilter::registerEvent(QWindow *window)
{
    if( window != nullptr )
    {
#ifdef Q_OS_WIN32
        GUID guid = ...;

        DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;

        ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
        NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
        NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        NotificationFilter.dbcc_classguid = guid;
        HDEVNOTIFY hDevNotify = RegisterDeviceNotification((HANDLE)window->winId(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
        if( NULL == hDevNotify )
        {
            // Print error
        }
#endif
    }

}

/** main.cpp **/
int main()
{
    ...
    DeviceEventFilter event_filter;
    QWindow *w = qApp->allWindows().first();
    event_filter.registerEvent(w);
    app.installNativeEventFilter(&event_filter);
    ...
}

【讨论】:

  • msg->wParam 等于 DBT_DEVICEARRIVAL 或 DBT_DEVICEREMOVECOMPLETE 仅当我插入(或拔出)USB 密钥时。例如,如果我插入鼠标,它就不起作用
  • 似乎只接收DBT_DEVNODES_CHANGED 是一个常见问题。您可能会发现以下内容很有趣:stackoverflow.com/questions/28998625/…
猜你喜欢
  • 1970-01-01
  • 2017-03-16
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多