主要是要实现一个SingleApplication…单实例
这里采用的方法是 LocalServer 的方式,网上大致都讲的很清楚了。
看了一下实现,也挺不错的,只加了两个文件就搞定了。
然后这里是个人精简版的,Windows模式下测试是没问题了。
首先是 SingleApplication.h 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#ifndef SINGLEAPPLICATION_H #define SINGLEAPPLICATION_H #include <QtWidgets/QWidget> #include <QObject> #include <QApplication> #include <QtNetwork/QLocalServer> #include <QtNetwork/QLocalSocket> class SingleApplication : public QApplication { Q_OBJECT public: SingleApplication(int &argc, char **argv); bool IsRunning(); //是否已经有实例在运行 void setMainWindow(QWidget* w); //设置主窗口界面指针 private slots: // 有新连接时触发 - 说明有新连接,则可以执行对应操作 void NewLocalConnection(); private: void InitLocalConnection(); //初始化本地连接 void NewLocalServer(); //创建服务端 void ActivateWindow(); //激活主窗口 private: bool isRunning; QLocalServer* localServer; QString serverName; QWidget* w; //主窗口界面指针 }; #endif //SINGLEAPPLICATION_H |
SingleApplication.cpp文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
#include "SingleApplication.h" #define TIME_OUT (200) //超时时间 200ms SingleApplication::SingleApplication(int &argc, char **argv) : QApplication(argc, argv) { w = NULL; isRunning = false; localServer = NULL; serverName = "TK - SSXPlayer"; //LocalServer的名称 //初始化本地连接 InitLocalConnection(); } //设置主窗口界面指针 void SingleApplication::setMainWindow(QWidget* w) { this->w = w; } //是否有实例在运行 bool SingleApplication::IsRunning() { return isRunning; } //通过socket通讯实现程序单实例运行,监听到新的连接时触发该函数 void SingleApplication::NewLocalConnection() { QLocalSocket *socket = localServer->nextPendingConnection(); if(socket) { socket->waitForReadyRead(2 * TIME_OUT); delete socket; //有通信连接上了,则可以显示窗口 ActivateWindow(); } } //初始化本地连接,如果连接不上server,则创建server,否则退出 void SingleApplication::InitLocalConnection() { isRunning = false; //连接服务器 QLocalSocket socket; socket.connectToServer(serverName); if(socket.waitForConnected(TIME_OUT)) { //连接上了,则说明有实例了 isRunning = true; // 其他处理,如:将启动参数发送到服务端 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::ActivateWindow() { if(w) { w->setWindowState(Qt::WindowState::WindowActive); w->show(); w->raise(); w->activateWindow(); //激活窗口 } } |
然后是 main函数下面的用法 – 这里可以对比着看
记得要替换头文件 – #include “SingleApplication.h”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//仅允许一个实例运行 SingleApplication app(argc, argv); if(app.IsRunning()) { //如果正在运行,则直接退出 //原实例会接受到一个链接,然后执行对应唤醒操作 exit(0); } //没有其他实例运行,则运行当前实例 SSXPlayer w; w.show(); //然后设置应用程序主窗口 app.setMainWindow(&w); //开始消息循环 return app.exec(); |
最后记录一点无关代码,可以忽略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
//存在的问题是,托盘模式下无法打开 ////查看当前应用成的 类名称 和 窗口名称 ////HWND hWnd = GetActiveWindow(); ////WCHAR buf[256] = {0}; ////GetClassName(hWnd, buf, 255); ////QString qstr(QString::fromStdWString(buf)); ////qDebug() << qstr << endl; ////ZeroMemory(buf, 256); ////GetWindowText(hWnd, buf, 255);//这样可以获取windowname ////qstr = QString::fromStdWString(buf); ////qDebug() << qstr << endl; ////3. 单实例,打开原实例 ////查找该应用程序是否已存在,如果已存在,则打开已存在程序 //QApplication a(argc, argv); //HWND pWndPrev, pWndChild; //if(pWndPrev = FindWindow(TEXT("Qt5QWindowIcon"), TEXT("SSXPlayer"))) //{ // if(IsWindowVisible(pWndPrev)) // { // qDebug() << "TRUE" << endl; // ShowWindow(pWndPrev, SW_RESTORE); // SetForegroundWindow(pWndPrev); // } // else // { // qDebug() << "FALSE" << endl; // } // exit(0); //} //else //{ // SSXPlayer w; // w.show(); // return a.exec(); //} ////1. 非单实例模式 //QApplication a(argc, argv); //SSXPlayer w; //w.show(); //return a.exec(); |
【Qt】Qt5下的SingleApplication的实现