使用QLocalServer,QLocalSocket实现单实例进程,当已经存在相同进程时且窗口未激活(遮挡,最小化,托盘)时,激活进程主窗口。
参考文章:http://blog.csdn.net/playstudy/article/details/7796691
#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H
#include <QObject>
#include <QApplication>
class QWidget;
class QLocalServer;
class SingleApplication : public QApplication
{
Q_OBJECT
public:
SingleApplication(int &argc, char **argv);
bool isRunning(); // 是否已经有实例在运行
QWidget *mainWindow; // MainWindow指针
private slots:
// 有新连接时触发
void newLocalConnection();
private:
// 初始化本地连接
void initLocalConnection();
// 创建服务端
void newLocalServer();
bool bRunning; // 是否已经有实例在运行
QLocalServer *localServer; // 本地socket Server
QString serverName; // 服务名称
};
#endif // SINGLEAPPLICATION_H
#include "SingleApplication.h"
#include <QWidget>
#include <QtNetwork/QLocalSocket>
#include <QtNetwork/QLocalServer>
#include <QFileInfo>
#include <QLibrary>
SingleApplication::SingleApplication(int &argc, char **argv)
: QApplication(argc, argv)
, bRunning(false)
, localServer(NULL)
, mainWindow(NULL)
{
// 取应用程序名作为LocalServer的名字
serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
//qDebug()<<serverName;
initLocalConnection();
}
// 说明:
// 检查是否已經有一个实例在运行, true - 有实例运行, false - 没有实例运行
bool SingleApplication::isRunning()
{
return bRunning;
}
// 说明:
// 通过socket通讯实现程序单实例运行,监听到新的连接时触发该函数
void SingleApplication::newLocalConnection()
{
QLocalSocket *socket = localServer->nextPendingConnection();
if (!socket)
return;
socket->waitForReadyRead(1000);
QTextStream stream(socket);
//其他处理
delete socket;
if (mainWindow != NULL)
{
//激活窗口
mainWindow->raise();
mainWindow->activateWindow();
mainWindow->setWindowState((mainWindow->windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
mainWindow->show();
}
}
// 说明:
// 通过socket通讯实现程序单实例运行,
// 初始化本地连接,如果连接不上server,则创建,否则退出
void SingleApplication::initLocalConnection()
{
bRunning = false;
QLocalSocket socket;
socket.connectToServer(serverName);
if(socket.waitForConnected(500))
{
bRunning = true;
// 其他处理,如:将启动参数发送到服务端
QTextStream stream(&socket);
QStringList args = QCoreApplication::arguments();
if (args.count() > 1)
stream << args.last();
else
stream << QString();
stream.flush();
socket.waitForBytesWritten();
return;
}
//连接不上服务器,就创建一个
newLocalServer();
}
// 说明:
// 创建LocalServer
void SingleApplication::newLocalServer()
{
localServer = new QLocalServer(this);
connect(localServer, SIGNAL(newConnection()), this, SLOT(newLocalConnection()));
if(!localServer->listen(serverName))
{
// 此时监听失败,可能是程序崩溃时,残留进程服务导致的,移除之
if(localServer->serverError() == QAbstractSocket::AddressInUseError)
{
QLocalServer::removeServer(serverName); // <-- 重点
localServer->listen(serverName); // 再次监听
}
}
}
如何使用:
1:在.pro文件中添加 QT += network
2:main.cpp如下
#include "mainwindow.h"
#include "SingleApplication.h"
int main(int argc, char *argv[])
{
//单实例进程,或者说防止程序多开
SingleApplication a(argc, argv);
if (!a.isRunning())
{
MainWindow w;
//传入一个要激活程序的窗口,当多开时会激活已有进程的窗口,且多开失败
a.mainWindow = &w;
w.show();
return a.exec();
}
return 0;
}
如果有发现无法激活窗口的童鞋,请更换系统环境测试。