现在的位置: 首页 > 综合 > 正文

qt main 函数的几个实用性的做法(包括单启动、检测usb接入事件)

2018年03月18日 ⁄ 综合 ⁄ 共 3048字 ⁄ 字号 评论关闭

1、QApplication::addLibraryPath()添加库文件路径。

2、Qt中实现单启动 QSharedMemory (The QSharedMemory class provides access to a shared memory segment.),调用create()函数,通过其返回值来判断程序是否申请过该内存,若申请过则可判断程序已经启动,从而退出程序。

3、Q_INIT_RESOURCE(name),用于初始化资源,有时找不到资源文件时可以尝试使用此方法。

4、QSplashScreen的使用,用于显示启动时的动画窗口。

5、当在windows中使用Qt进行编程时,要处理windwos的中Qt没有处理的事件,例如usb设备的接入事件

      此时可以重新实现bool QWidget::winEvent(MSG*msg,long*result),也可以重新实现bool
QCoreApplication::winEventFilter ( MSG * msg, long * result ),但建议重新实现bool QWidget::winEvent(MSG *msg, long *result)

如果不对某个窗体句柄注册申请设备通知,则每次不管设备接入还是拔出,msg->wParam值均为7(DBT_DEVNODES_CHANGED),达不到我们所要的结果,向系统申请设备通知的代码如下(可以在主窗口的构造函数中使用):

    DEV_BROADCAST_VOLUME pDevBroadCastData;
    pDevBroadCastData.dbcv_size = sizeof(DEV_BROADCAST_VOLUME);
    pDevBroadCastData.dbcv_devicetype  = DBT_DEVTYP_VOLUME;

    HDEVNOTIFY deviceNotifier = RegisterDeviceNotification(winId(),
                                                           &pDevBroadCastData,
                                                           DEVICE_NOTIFY_WINDOW_HANDLE);

注意头文件中必须按如下顺序包含

#define _WIN32_WINNT 0x0500

//#define _WIN32_WINDOWS 0x0500

#define WINVER 0x0500

#include <windows.h>

#include <dbt.h>

如果不按照以上顺序写,则可能出现如下错误:

error: 'DEVICE_NOTIFY_WINDOW_HANDLE' was not declared in this scope

error: 'RegisterDeviceNotificationW' was not declared in this scope

主要是以上蓝色区域文字条件编译的结果。

/*------------------------------------------------------------------
   FirstDriveFromMask (unitmask)

   Description
     Finds the first valid drive letter from a mask of drive letters.
     The mask must be in the format bit 0 = A, bit 1 = B, bit 3 = C,
     etc. A valid drive letter is defined when the corresponding bit
     is set to 1.

   Returns the first drive letter that was found.
--------------------------------------------------------------------*/

char FirstDriveFromMask(quint32 unitmask)
{
    char i;

    for (i = 0; i < 26; ++i)
    {
        if (unitmask & 0x1)
            break;
        unitmask = unitmask >> 1;
    }

    return (i + 'A');
}

(a)

bool MainWindow::winEvent(MSG* msg, long * result)
{
    bool bResult = false;
    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 lpdbInterface =
                    (PDEV_BROADCAST_VOLUME)lpdb;
            char diskID = FirstDriveFromMask(
                        lpdbInterface->dbcv_unitmask);
            QString mountedName = QString::fromAscii(&diskID, 1);
            mountedName = mountedName + ":\\";
            appearedDeivce(mountedName);
        }

        bResult = true;

        break;

    case DBT_DEVICEREMOVECOMPLETE:
        if(lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
        {
            PDEV_BROADCAST_VOLUME lpdbInterface =
                    (PDEV_BROADCAST_VOLUME)lpdb;
            char diskID = FirstDriveFromMask(
                        lpdbInterface->dbcv_unitmask);
            QString mountedName = QString::fromAscii(&diskID, 1);
            mountedName = mountedName + ":\\";
            disAppearedDevice(mountedName);
        }

        bResult = true;
        break;

    default:
        bResult = true;
        break;
    }	
}

(b)

最后,如果重新实现bool QCoreApplication::winEventFilter ( MSG * msg, long * result )可能导致一个问题,就是每次设备的插入和弹出事件将接受两次,所以,建议重新实现bool QWidget::winEvent(MSG*msg,long*result)。

后来重新测试,其实直接重新实现bool QCoreApplication::winEventFilter ( MSG * msg, long * result )也能实现,且无需向系统申请设备通知,直接拷贝代码(a)、(b)并修改为相应的函数名,但有一点需要注意,在Qt中调试,断点不能打在switch语句处,否则每次均只能接收到7(DBT_DEVNODES_CHANGED),直接打开case内即可进入。


6、关于usb设备,由于如果打开软件之前,设备已经接入,则无法收到usb设备的接入事件,导致软件中无法正确显示。

GetLogicalDriveStrings()函数来查询当前所有逻辑驱动器的根驱动器路径;

GetDriveType()判断一个磁盘驱动器的类型;

CreateFile()打开一个设备句柄;

DeviceIoControl()对打开的设备句柄进行操作;

CloseHandle()关闭设备句柄;

GetDiskFreeSpace()获取与一个磁盘的组织有关的信息,以及了解剩余空间的容量;

抱歉!评论已关闭.