How to know when a new USB storage device is connected in Qt?
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
Is there a Qt solution for detecting USB events (insertion and removal)?
As already pointed out, Qt itself does not provide such a module. There is however a user-made class called QDeviceWatcher
. I have no experience with it personally and it is not updated regularly but you could give it a try.
You can find the forum post here and the git repository here.
Find current connected USB storage path in C++
First you need to get removable drives:
void EnumUsbDrives() {
DWORD drv = ::GetLogicalDrives();
if (drv == 0) return;
DWORD mask = 1;
TCHAR szDrive[] = _TEXT("?:\\");
for (uint_t i = 0; i < ('Z' - 'A' + 1); i++, mask <<= 1) {
if (drv & mask) {
szDrive[0] = (TCHAR)(_T('A') + i);
if (::GetDriveType(szDrive) == DRIVE_REMOVABLE) {
bool bUSB = IsDriveUSB(szDrive);
if (bUSB) {
// Time do to something useful
}
}
}
}
}
Function IsDriveUSB is a bit more complicated. I have teared it from an in-house library; the function uses custom helper classes xregistry and xstring_nocase. Their purpose is pretty obvious, I believe you will have no trouble replacing it with other similar classes or API calls.
bool IsDriveUSB (LPCTSTR szDrive) throw() {
TCHAR szLogicalDrive[] = _TEXT("\\\\.\\x:");
szLogicalDrive[4] = szDrive[0];
HANDLE hDrive = ::CreateFile(szLogicalDrive, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDrive == INVALID_HANDLE_VALUE) return false; // Can't open drive so we have to assume the drive is fixed
VOLUME_DISK_EXTENTS vde;
DWORD dwBytesReturned = 0;
BOOL br = ::DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &vde, sizeof(vde), &dwBytesReturned, NULL);
::CloseHandle(hDrive);
if (!br) return false; // Can't get extents info so we have to assume the drive is fixed
if (vde.NumberOfDiskExtents != 1) return false;
ULONG uPhysDrive = vde.Extents[0].DiskNumber;
TCHAR szPhysDrive[16];
_stprintf(szPhysDrive, _TEXT("%u"), uPhysDrive);
try {
xregistry rk(HKEY_LOCAL_MACHINE, OS.Is64bit());
rk.open(_TEXT("SYSTEM\\CurrentControlSet\\services\\Disk\\Enum"), KEY_QUERY_VALUE);
if (!rk.value_exists(szPhysDrive)) return false;
xstring_nocase strInterface = rk.get_string(szPhysDrive).substring(0, 7);
return strInterface == _TEXT("USBSTOR");
}
catch (...) {
return false;
}
}
Related Topics
C++ - Get Value of a Particular Memory Address
Does the Alignas Specifier Work with 'New'
Setting Extra Bits in a Bool Makes It True and False at the Same Time
Using C++ Aggregate Initialization in Std::Make_Shared
Partial Template Specialization Based on "Signed-Ness" of Integer Type
How to Implement an Easy_Bind() That Automagically Inserts Implied Placeholders
Floating Point to Binary Value(C++)
Test Whether a Class Is Polymorphic
How to Control Memory Allocation Strategy in Third Party Library Code
Popen() Writes Output of Command Executed to Cout
Value-Initializing an Automatic Object
Could Not Load Spatialite Extension in Qsqlite ( Qt 5.9)
Std::Istream_Iterator<> with Copy_N() and Friends
Gcc 7, -Wimplicit-Fallthrough Warnings, and Portable Way to Clear Them