我有一个填充有QFileSystemModel的QTreeView,并将根路径设置为“ \”(作为“ \\”)。这工作得很好,并且可以看到本地驱动器和USB驱动器。我的问题是,当我使用DeviceIoControl(...,FSCTL_DISMOUNT_VOLUME,...)以编程方式弹出USB驱动器(我正在以信息亭模式为Win7应用程序编程,因此它需要处理Windows级活动)时,随后通过DeviceIoControl(...,IOCTL_STORAGE_EJECT_MEDIA,...),尽管两个函数都返回true,并且Windows系统服务托盘未显示USB图标,并且Windows资源管理器没有USB条目,但我的QFileSystemModel仍然看到驱动器。
我确实有一个从QSortFilterProxyModel派生的代理模型,并且正在过滤所看到的内容,因为我真的只想查看USB驱动器。这正在调用我的USBController类来检测已安装的可移动设备。该函数调用GetLogicalDrives(),它实际上返回我刚刚以编程方式弹出的USB的驱动器号。
我一直在寻找解决这个难题的方法,但是还没有解决这个难题。有没有人有什么建议?以下是相关代码:
来自UsbController.h的函数:
bool UsbController::ejectDrive(char driveletter, QString &errmsg)
{
char devicepath[7];
char format[] = "\\\\.\\?:";
strcpy_s(devicepath, format);
devicepath[4] = driveletter;
errmsg = "";
DWORD dwRet = 0;
wchar_t wtext[7];
size_t textlen = 7;
mbstowcs_s(&textlen, wtext, devicepath,strlen(devicepath)+1);
HANDLE hVol = CreateFile(wtext, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hVol == INVALID_HANDLE_VALUE)
{
FormatErrorMsg("CreateFile: ", errmsg);
return false;
}
if(!DeviceIoControl(hVol, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dwRet, 0))
{
FormatErrorMsg("Lock Volume: ", errmsg);
return false;
}
if(!DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dwRet, 0))
{
FormatErrorMsg("Dismount Volume: ", errmsg);
return false;
}
if (!DeviceIoControl(hVol, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &dwRet, 0))
{
FormatErrorMsg("Eject Media: ", errmsg);
return false;
}
CloseHandle(hVol);
return true;
}
QMap<QString,QString> UsbController::getMountedRemovables()
{
DWORD test = GetLogicalDrives();
DWORD mask = 1;
UINT type = 0;
WCHAR wdrive[] = L"?:\\"; // use as a drive letter template
QMap<QString,QString> removables;
for (int i = 0; i < 32; i++)
{
if (test & mask)
{
wdrive[0] = (char)('A' + i); // change letter in template
type = GetDriveType(wdrive);
switch (type) {
case DRIVE_REMOVABLE:
{
QString qdrive = QString((char)('A' + i)) + ":";
if (!removables.contains(qdrive))
{
QString name = mountNameFromDriveLetter((char)('A' + i));
removables.insert(qdrive, name);
}
break;
}
default: break;
}
}
mask = mask << 1;
}
return removables;
}
我的代理模型中的功能(数据使用了acceptedRemovables QMap,该QMap通过调用UsbController填充在detectMountedRemovables()中:
QVariant DriveFilterProxyModel::data(const QModelIndex & index, int role) const
{
QVariant data = QSortFilterProxyModel::data(index, role);
if (role == Qt::DisplayRole)
{
QString source = data.toString();
for (int i = 0; i < acceptList.size(); i++)
{
if (source.contains(acceptList[i]))
{
QString drivestring = source;
if (drivestring.contains('('))
{
drivestring = drivestring.remove(0, drivestring.indexOf('(')+1);
drivestring = drivestring.remove(drivestring.indexOf(')'), drivestring.size()-drivestring.indexOf(')')+1);
}
QMap<QString,QString>::const_iterator iter = acceptedNonRemovables.find(drivestring);
if (iter != acceptedNonRemovables.end())
{
if (source.contains("Data")) // no path as yet applied
{
QString newsource(source);
newsource.replace("Data", iter.value());
qDebug() << "DriveFilterProxyModel::filterAcceptsRow(): Mapped drive: should replace \"Data\" with: " << iter.value() << " to produce: " << newsource;
return newsource;
}
}
else
{
iter = acceptedRemovables.find(drivestring);
if (iter != acceptedRemovables.end())
{
if (!source.contains('(')) // no drive name found
{
QString newsource = QString("Removable Disk (%1)").arg(source);
qDebug() << "DriveFilterProxyModel::filterAcceptsRow(): USB drive: should change simple drive letter to: " << newsource;
return newsource;
}
}
}
}
}
}
return data;
}
void DriveFilterProxyModel::detectMountedRemovables()
{
acceptedRemovables = UsbController::getMountedRemovables();
resetAcceptList();
}
最佳答案
我猜该驱动器仍可被系统识别,但仍处于退出模式。
看一下Enumerating all available drive letters in Windows问题,可能是您在那里找到了可行的解决方案。
关于c++ - c++ Qt/Win32-USB以编程方式弹出,但仍显示在QFileSystemModel和GetLogicalDrives()中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29102553/