How to know when a new USB storage device is connected in Qt?

14,135

Solution 1

I believe what you may be missing is the call to register for device notification. Here is code that I use to do the same thing, though I override the winEvent() method of the QWidget class and not the winEventFilter.

// Register for device connect notification
DEV_BROADCAST_DEVICEINTERFACE devInt;
ZeroMemory( &devInt, sizeof(devInt) );
devInt.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
devInt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
devInt.dbcc_classguid = GUID_DEVINTERFACE_VOLUME;

m_hDeviceNotify =
    RegisterDeviceNotification( winId(), &devInt, DEVICE_NOTIFY_WINDOW_HANDLE );   
if(m_hDeviceNotify == NULL)
{
    qDebug() << "Failed to register device notification";
} // end if

NOTE: You will most likely need to change the values of the DEV_BROADCAST_DEVICEINTERFACE to fit your needs.

EDIT: To use this code you will need to include the proper header files and perform the proper setup. DEV_BROADCAST_DEVICEINTERFACE requires the Dbt.h header to be included. Also, the focal point of this code is on the RegisterDeviceNotification function. Info is available on MSDN

Solution 2

I'm working along the same lines but in C#.

you need to register your application with the system (look at the RegisterHidNotification() function). Mine looks like this: `

void RegisterHidNotification() //Register this application to recieve all USB device notices

        {
            BroadcastHeader dbi = new BroadcastHeader();
            int size = Marshal.SizeOf(dbi);
            dbi.Size = size;
            dbi.Type = DeviceType.DeviceInterface;
            **dbi.Classguid = GUID_DEVINTERFACE_USB_DEVICE**;
            dbi.Name = 0;
            IntPtr buffer = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(dbi, buffer, true);
            IntPtr r = RegisterDeviceNotification(this.Handle, buffer, (int)DeviceEvents.regWindowHandle);
            if (r == IntPtr.Zero)
                statusLabel.Text = GetLastError().ToString();
        }`

The most important part of the function is the bit I've highlighted in bold (or at least tried to). Defined as: public Guid GUID_DEVINTERFACE_USB_DEVICE = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED"); Hope you can adapt it to your application.

Solution 3

You can easily reimplement QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result) and check for device connection :

    #ifdef Q_OS_WIN
    #include <Dbt.h>
    #endif

    bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) {
#ifdef Q_OS_WIN
        MSG* msg = reinterpret_cast<MSG*>(message);
        if (msg->message == WM_DEVICECHANGE) {
            switch (msg->wParam) {
            case DBT_DEVICEARRIVAL:
                qDebug() << "connected";
                break;
            case DBT_DEVICEREMOVECOMPLETE:
                qDebug() << "disconnected";
                break;
            default:
                break;
            }
        }
#endif // Q_OS_WIN
        return false;
    }
Share:
14,135
Skilldrick
Author by

Skilldrick

I started working at Twitter in November 2011. Loving it so far :) I've got a blog at http://skilldrick.co.uk where I talk about programming (mostly JavaScript and Ruby at the moment). Blog Twitter LinkedIn Stack Overflow Careers CV

Updated on June 07, 2022

Comments

  • Skilldrick
    Skilldrick almost 2 years

    I want to know when a USB device is connected to the computer that my Qt application is running on (in Windows). In my main QWidget, I've reimplemented winEventFilter like this:

    bool winEventFilter ( MSG * msg, long * result ) {
        qDebug() << msg;
        return false;
    }
    

    I'd expect qDebug to send at least something when I connect a USB device, but I don't get anything.

    I'm guessing that I'm fundamentally misunderstanding the process here - this is my first Qt app!

  • Skilldrick
    Skilldrick almost 15 years
    Sorry to be dumb, but I can't make DEV_BROADCAST_DEVICEINTERFACE work (error: `DEV_BROADCAST_DEVICEINTERFACE' was not declared in this scope). Do I need to include extra header files?
  • brader24
    brader24 almost 15 years
    Don't be sorry. I had a tough time figuring a lot of this out myself. Hopefully my edit will give you some direction on how to use the code I gave. It still may not be complete though. I included the link to MSDN to give you a source for more info. If I had more time, I'd try to give you a more thorough direction on how to implement it. This really should at least get the messages to your handler.