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()获取与一个磁盘的组织有关的信息,以及了解剩余空间的容量;