Qt5 在 Windows 环境下检测U盘的插入和拔出

目录 Content
[hide]

作为数据交换媒体,U盘目前还是常用的一种形式。在实用的App中,就存在检测U盘插入和拔出的需求。LT 对这个需求做了一些搜索和验证,结果当然是做出来了。不过感受到网络上的资料并不是拿来就能用的,还需要分析和判断。

一、编译成功却没效果

如果你以关键字 “qt windows 检测U盘”进行搜索,那么多半找到的是下列的代码

#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui/QWidget>
#include <dbt.h>
#include <windows.h>
#include <QString>
class Widget : public QWidget
{
	Q_OBJECT
public:
	Widget(QWidget *parent = 0);
	~Widget();
protected:
	bool winEvent(MSG *msg, long *result);
private:
	//UsbConfig usbConfig;
	char FirstDriveFromMask (ULONG unitmask);
};
#endif // WIDGET_H


#include "widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
	: QWidget(parent)
{
}
Widget::~Widget()
{
}
bool Widget::winEvent(MSG *msg,long *result)
{
	int msgType = msg->message;
	if(msgType == WM_DEVICECHANGE)
	{
		qDebug() << "winEvent in MgFrame : WM_DEVICECHANGE" ;
		PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;
		switch(msg->wParam)
		{
		case DBT_DEVICEARRIVAL:
			if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
			{
				PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
				if (lpdbv -> dbcv_flags == 0)
				{
					// 插入U盘,此处可以做你想做的事
					QString USBDisk = QString(this->FirstDriveFromMask(lpdbv ->dbcv_unitmask));
					qDebug() << "USB_Arrived and The USBDisk is: "<<USBDisk ;
				}
			}
			break;
				   case DBT_DEVICEREMOVECOMPLETE:
			if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
			{
				PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
				if (lpdbv -> dbcv_flags == 0)
				{
					// 拔出U盘,此处可以做你想做的事
					qDebug() << "USB_Removed";
				}
			}
			break;
		}
	}
	return false;
}
char Widget::FirstDriveFromMask (ULONG unitmask)
{
	char i;
	for (i = 0; i < 26; ++i)
	{
		if (unitmask & 0x1)
			break;
		unitmask = unitmask >> 1;
	}
	return (i + 'A');
}


然而,看到

#include <QtGui/QWidget>

第一反应就是Qt4的代码,于是修改成Qt5的方式,可是,编译通过了,插入U盘却没有任何反应?

怎么回事?

二、winEvent 与 nativeEvent

原来是 Qt5 取消了 winEvent ,而用 nativeEvent 取而代之,原因就这么简单,但是上述代码难道就不能用了? 于是继续搜索,又找到一篇 《QT5进程间通信-消息传递》,但是他的代码还是不能直接使用,需要做些修改。

三、功能完美实现

在 LT 修改后,代码终于发挥出强大的功能,插入U盘检测后,即会用qDebug()输出消息。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <windows.h>
#include <QMainWindow>
#include <dbt.h>
#include <QString>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    char FirstDriveFromMask (ULONG unitmask);

protected:
    bool nativeEvent(const QByteArray & eventType, void * message, long*result);

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

char MainWindow::FirstDriveFromMask(ULONG unitmask)
{
    char i;
    for (i = 0; i < 26; ++i)
    {
        if (unitmask & 0x1)
            break;
        unitmask = unitmask >> 1;
    }
    return (i + 'A');
}

bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    MSG* msg = reinterpret_cast<MSG*>(message);
    int msgType = msg->message;
    if(msgType==WM_DEVICECHANGE)
    {
        PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)msg->lParam;
        switch (msg->wParam) {
        case DBT_DEVICEARRIVAL:

            if(lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
                PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
                if(lpdbv->dbcv_flags ==0)
                {
                    QString USBDisk = QString(this->FirstDriveFromMask(lpdbv ->dbcv_unitmask));
                    qDebug() << "USB_Arrived and The USBDisk is: "<<USBDisk ;

                }
            }
            break;
        case DBT_DEVICEREMOVECOMPLETE:
            if(lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)
            {
                PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
                if(lpdbv->dbcv_flags == 0)
                {
                    qDebug() << "USB_Removed";

                }
            }
            break;
        }
    }
    return false;

}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

效果如图

Qt5_Win7_Udisk

四、源码下载

在 Win7 X64 和 Qt 5.3.2 下测试通过

关键字: winEvent, nativeEvent  qt5, U盘

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.