四、Qt之保证本地只有一个应用程序启动,禁止多开(另QLocalServer、QLocalSocket使用案例)
SingleApplication.h#ifndef SINGLEAPPLICATION_H#define SINGLEAPPLICATION_H#include <QObject>#include <QApplication>class QMainWindow;class QLocalServer;class SingleApplication : pu...
·
SingleApplication.h
#ifndef SINGLEAPPLICATION_H
#define SINGLEAPPLICATION_H
#include <QObject>
#include <QApplication>
class QMainWindow;
class QLocalServer;
class SingleApplication : public QApplication
{
Q_OBJECT
public:
SingleApplication(int &args, char **argv);
bool getInstanceRunning() const; // 是否已经有实例在运行
QMainWindow *getMainWindow() const;
void setMainWindow(QMainWindow *value);
private slots:
void newLocalConnection();
private:
void initLocalConnection(); // 初始化本地连接
void newLocalServer(); // 创建服务端
bool instanceRunning; // 是否已经有实例在运行
QLocalServer *localServer; // 本地socket Server(用于本地进程间通信)
QString serverName; // 服务名称
QMainWindow *mainWindow; // MainWindow指针
};
#endif // SINGLEAPPLICATION_H
SingleApplication.cpp
#include "singleapplication.h"
#include <QMainWindow>
#include <QtNetwork/QLocalServer>
#include <QtNetwork/QLocalSocket>
#include <QFileInfo>
#include <QMessageBox>
SingleApplication::SingleApplication(int &args, char **argv) :
QApplication(args, argv),
instanceRunning(false),
localServer(NULL),
mainWindow(NULL)
{
/**
* 一般来说是取引用程序名作为 localServer 的进程服务名
* 目前程序的进程名是根据文件名来的,但是一旦用于更改了文件名,那么进程名就不准确了,
* 所以通过文件名来判断是进程服务是不可靠的,应该写死在代码里
*/
// serverName = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
serverName = "TestServerName";
initLocalConnection();
}
void SingleApplication::initLocalConnection()
{
instanceRunning = false;
QLocalSocket socket;
//将套接字连接至进程服务,参数即为进程服务名
socket.connectToServer(serverName);
//若在500ms内连接至进程服务,说明进程服务已运行
if (socket.waitForConnected(500)) {
instanceRunning = 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); //再次监听
}
}
}
void SingleApplication::newLocalConnection()
{
//监听进程服务,当有数据进来时,可以通过 nextPendingConnection() 获取套接字
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();
QMessageBox::warning(NULL, "警告", "程序已经启动!");
}
}
////////////////////////////////////////////////////////////////////////////////
// 说明:
// 检查是否已有一个实例在运行, true - 有实例运行, false - 没有实例运行
////////////////////////////////////////////////////////////////////////////////
bool SingleApplication::getInstanceRunning() const
{
return instanceRunning;
}
QMainWindow *SingleApplication::getMainWindow() const
{
return mainWindow;
}
void SingleApplication::setMainWindow(QMainWindow *value)
{
mainWindow = value;
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include "singleapplication.h"
int main(int argc, char *argv[])
{
SingleApplication a(argc, argv);
if (!a.getInstanceRunning()) {
MainWindow w;
a.setMainWindow(&w);
w.show();
return a.exec();
}
return 0;
}
更多推荐
所有评论(0)