原理是使用Qt的QLocalServer和QLocalSocket類創建一個虛擬服務端(因爲不是真實的socket,所以稱之爲虛擬)。
程序啓動時檢測同名服務端是否啓動,如果服務端已經啓動,則退出,否則創建一個服務端並繼續啓動。
代碼如下:
頭文件:
#include <QApplication>
class QLocalServer;
class YxsSingleApplication : public QApplication
{
Q_OBJECT
public:
YxsSingleApplication(int &argc, char **argv);
~YxsSingleApplication();
bool isRunning();
public slots:
void slotNewConnection();
private:
void initConnection();
void createServer();
void setWindowActivated();
private:
QWidget *m_widget;
QLocalServer *m_server;
QString m_server_name;
bool m_isRunning;
};
YxsSingleApplication::YxsSingleApplication(int &argc, char **argv) :
QApplication(argc, argv),
m_widget(0),
m_server(0),
m_server_name(""),
m_isRunning(false)
{
m_server_name = QFileInfo(QCoreApplication::applicationFilePath()).fileName();
initConnection();
}
YxsSingleApplication::~YxsSingleApplication()
{
}
bool YxsSingleApplication::isRunning()
{
return m_isRunning;
}
void YxsSingleApplication::slotNewConnection()
{
QLocalSocket *socket = m_server->nextPendingConnection();
if (socket)
{
socket->waitForReadyRead(1000);
delete socket;
setWindowActivated();
}
}
void YxsSingleApplication::initConnection()
{
QLocalSocket socket;
// 連接以應用程序名稱爲server name的server
// 如果連接不上則代表未啓動,此時創建一個新的server
m_isRunning = false;
socket.connectToServer(m_server_name);
if (socket.waitForConnected(500))
{
m_isRunning = true;
return;
}
createServer();
}
void YxsSingleApplication::createServer()
{
m_server = new QLocalServer(this);
connect(m_server, SIGNAL(newConnection()), this, SLOT(slotNewConnection()));
if (!m_server->listen(m_server_name))
{
// 此時監聽失敗,可能是程序崩潰是殘留進程的服務所導致,移除
if (QAbstractSocket::AddressInUseError == m_server->serverError())
{
QLocalServer::removeServer(m_server_name);
m_server->listen(m_server_name);
}
}
}
void YxsSingleApplication::setWindowActivated()
{
if (m_widget)
{
m_widget->show();
m_widget->raise();
m_widget->activateWindow();
}
}
使用方式:
int main(int argc, char *argv[])
{
YxsSingleApplication app(argc, argv);
if (!app.isRunning())
{
YxsMainWindow win;
win.show();
return app.exec();
}
return 0;
}