目录

1.exe图标设置

2.托盘设置

3.当关闭最后窗口时程序仍然后台运行

4.多次点击exe只执行一次

5.消息重定向到textEdit

6.读写ini文件

7.exe所在路径

8.当前时刻获取

9.设置窗口图标背景

10.状态栏

11.并发tcp服务器

12.tcp客户端

13.开机自启

14.获取桌面背景窗口

15.64位32位自动切换库文件

本文均是本人的一些总结,可能有不严谨的地方还请指出

(大概会持续更新吧)

1.exe图标设置

将ico图标与logo.rc文件放进pro目录中(3文件同目录)

logo.rc中写IDI_ICON1 ICON DISCARDABLE "icon.ico"

pro中加RC_FILE += logo.rc即可

2.托盘设置

头文件

#include <QSystemTrayIcon>
#include <QMenu>
QSystemTrayIcon *m_systemTray;//托盘
QMenu *m_trayMenu;//托盘菜单

托盘初始化示例,放入MainWindow构造函数调用

void MainWindow::InitTray()//初始化托盘
{m_systemTray = new QSystemTrayIcon(this);//托盘m_systemTray->setIcon(QIcon(":/res/image/icon.ico"));//托盘图标m_systemTray->setToolTip("xxxxx");//托盘提示m_trayMenu = new QMenu(this);//托盘菜单m_trayMenu->addAction("显示控件窗口", this, &MainWindow::show);m_trayMenu->addAction("退出", this, [=]{QApplication::quit();//退出});m_systemTray->setContextMenu(m_trayMenu);connect(m_systemTray, &QSystemTrayIcon::activated, this, [=](QSystemTrayIcon::ActivationReason s){if(s == QSystemTrayIcon::DoubleClick)   this->show();//鼠标双击显示});m_systemTray->show();
}

3.当关闭最后窗口时程序仍然后台运行

main函数中设置

//关闭窗口但不退出
QApplication::setQuitOnLastWindowClosed(false);

4.多次点击exe只执行一次

#include "mainwindow.h"#include <QApplication>
#include <QSharedMemory>int main(int argc, char *argv[])
{QSharedMemory shared("xxxxx");//创建共享内存,保证程序单实例运行if(shared.attach()) return -1;shared.create(1);QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}

5.消息重定向到textEdit

由于textEdit在子线程调用会导致崩溃,所以以全局的队列实现,qt的队列是线程安全的

首先写个全局调用的头文件Globel.h吧,通常我喜欢把多个线程访问的东西写在Globel

#ifndef GLOBEL_H
#define GLOBEL_H
#include <QCoreApplication>
#include <QTime>
#include <QQueue>#define LOCAL_TIME QTime::currentTime().toString()
#define WORK_PATH QCoreApplication::applicationDirPath()
#define MSG_QUEUE_MAX_LEN 20 //消息队列最大容量extern QQueue<QString> g_msgQueue;//消息队列
/**********************************************/
//注意把g_msgQueue定义一遍,比如在对应cpp定义
//#include "Globel.h"
//QQueue<QString> g_msgQueue;//消息队列
/**********************************************///全局类
class Globel
{
public://输出消息回调static void LogoutputToTextedit(QtMsgType, const QMessageLogContext&, const QString &msg){QString text;text.append(LOCAL_TIME);text.append(msg);if(g_msgQueue.size() >= MSG_QUEUE_MAX_LEN) return;g_msgQueue.enqueue(text);}//设置消息重定向static void SetMsgToQueue(){qInstallMessageHandler(LogoutputToTextedit);}static QString GetMsg()//获取消息{return g_msgQueue.empty() ? QString() : g_msgQueue.dequeue();}};#endif // GLOBEL_H

mainwindow构造中

ui->setupUi(this);
Globel::SetMsgToQueue();//设置消息重定向
//timer
m_timer = new QTimer;
connect(m_timer, &QTimer::timeout,this, [=]{QString msg = Globel::GetMsg();//获取消息if(!msg.isNull())ui->textEdit->append(msg);
});
m_timer->start(10);//10ms

6.读写ini文件

头文件#include <QSettings>

void MainWindow::SaveUsersData()//保存用户数据
{QSettings *userdata_iniwrite = new QSettings("userdata.ini", QSettings::IniFormat);userdata_iniwrite->setValue("tcp/ip", m_serverIp);userdata_iniwrite->setValue("tcp/port", QString::number(m_serverPort));userdata_iniwrite->deleteLater();
}void MainWindow::ReadUsersData()//读取用户数据
{QSettings *userdata_iniread = new QSettings("userdata.ini", QSettings::IniFormat);m_serverIp = userdata_iniread->value("tcp/ip").toString();m_serverPort = userdata_iniread->value("tcp/port").toUInt();userdata_iniread->deleteLater();
}

特别地,需要读取中文则需要添加

userdata_iniread->setIniCodec(QTextCodec::codecForName("UTF-8")); //重点

7.exe所在路径

当windows程序开机自启后,./就不是exe所在路径了,可通过下面方法获得WORK_PATH

#include <QCoreApplication>#define WORK_PATH QCoreApplication::applicationDirPath()

8.当前时刻获取

#define LOCAL_TIME QTime::currentTime().toString()

9.设置窗口图标背景

this->setWindowIcon(QIcon(":/res/image/icon.ico"));//设置窗口图标//只设置当前对象的背景
this->setStyleSheet("#MainWindow{border-image:url(:/res/image/bg.jpeg)}");
//设置当前对象及其子对象的背景
this->setStyleSheet("border-image:url(:/res/image/bg.jpeg)");

10.状态栏

头文件#include <QStatusBar>,附带个#include <QLabel>

m_statusLabel = new QLabel;
m_statusBar = new QStatusBar;
m_statusBar->addWidget(m_statusLabel);
//接下来操作m_statusLabel即可

11.并发tcp服务器

记得pro文件配置QT += network

首先继承一个QTcpServer,重写virtual void incomingConnection(qintptr handle),这里用数组实现的,当然用链表挺好。

"tcpsockettask.h"就是连接后的处理了,下面说

#ifndef MYTCPSEVER_H
#define MYTCPSEVER_H#include <QObject>
#include <QTcpServer>
#include <QQueue>#include "tcpsockettask.h"#define MAX_CONNECT_NUM 50//管理tcp任务对象结构体
struct TcpSocketTaskControl
{TcpSocketTaskControl() : tcp_task(nullptr), exist(false){}TcpSocketTask *tcp_task;//tcp任务对象bool exist;//对象存在性
};//自定义QTcpServer类
class MyTcpSever : public QTcpServer
{Q_OBJECT
public:explicit MyTcpSever(QObject *parent = nullptr) : QTcpServer(parent), m_count(0){qDebug() << "构造Tcp服务器,本服务器最大承载数" << MAX_CONNECT_NUM;}void ClearTcpTask()//清理tcp任务对象{qDebug() << "清理tcp任务对象";for(int i = 0; i < MAX_CONNECT_NUM; i++){if(m_tcpSocketTaskControl[i].exist == true){m_tcpSocketTaskControl[i].tcp_task->quit();m_tcpSocketTaskControl[i].tcp_task->wait();delete m_tcpSocketTaskControl[i].tcp_task;m_tcpSocketTaskControl[i].exist = false;m_count--;//tcp任务对象计数qDebug() << "清理" << i << "号tcp任务对象";}}qDebug() << "清理tcp任务对象完毕,tcp任务对象计数: " << m_count;}inline int GetTaskNum() const {return m_count;}//获取tcp任务对象计数protected:virtual void incomingConnection(qintptr handle)//新连接来临处理函数重写{for(int i = 0; i < MAX_CONNECT_NUM; i++){if(m_tcpSocketTaskControl[i].exist == true){if(m_tcpSocketTaskControl[i].tcp_task->isFinished())//线程运行结束了{m_tcpSocketTaskControl[i].tcp_task->quit();m_tcpSocketTaskControl[i].tcp_task->wait();delete m_tcpSocketTaskControl[i].tcp_task;m_tcpSocketTaskControl[i].exist = false;m_count--;//tcp任务对象计数qDebug() << "清理" << i << "号tcp任务对象";}}}for(int i = 0; i < MAX_CONNECT_NUM; i++){if(m_tcpSocketTaskControl[i].exist == false){m_tcpSocketTaskControl[i].exist = true;m_tcpSocketTaskControl[i].tcp_task = new TcpSocketTask(handle);//新的连接建立时触发槽函数m_tcpSocketTaskControl[i].tcp_task->start();//开始线程m_count++;//tcp任务对象计数qDebug() << "分配到" << i << "号tcp任务对象";break;}if(i == MAX_CONNECT_NUM - 1)qDebug() << "[错误] tcp任务对象已经分配满!";}qDebug() << "tcp任务对象计数: " << m_count;}private:TcpSocketTaskControl m_tcpSocketTaskControl[MAX_CONNECT_NUM];//管理tcp任务对象结构体int m_count;//tcp任务对象计数
};#endif // MYTCPSEVER_H

"tcpsockettask.h"连接后的处理

#ifndef TCPSOCKETTASK_H
#define TCPSOCKETTASK_H#include <QObject>
#include <QThread>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
#include <QByteArray>#define TCP_BUFFER_HEAD 0xffff //tcp传输头
#define FACE_SEND_INV 500 //间隔//TcpSocket任务类
class TcpSocketTask : public QThread
{Q_OBJECT
public:explicit TcpSocketTask(qintptr handle) : m_handle(handle){}protected:virtual void run()//线程执行函数重写{//initm_head = TCP_BUFFER_HEAD;head_buffer.append(m_head>>24).append(m_head>>16).append(m_head>>8).append(m_head);m_timer_send_text = new QTimer;//tcpm_tcpSocket = new QTcpSocket;if(m_tcpSocket->setSocketDescriptor(m_handle) == false) return;//根据描述符得到tcpsocket对象qDebug() << "与客户端建立连接: " + m_tcpSocket->peerAddress().toString() << m_tcpSocket;connect(m_tcpSocket, &QTcpSocket::readyRead, this, [=](){//收到tcp包时触发槽函数m_tcpSocket->readAll();//哪怕不用也得读出来}, Qt::DirectConnection);connect(m_tcpSocket, &QTcpSocket::disconnected, this, [=](){//连接断开时触发槽函数m_timer_send_text->stop();m_tcpSocket->close();qDebug() << "断开连接: " + m_tcpSocket->peerAddress().toString() << m_tcpSocket;this->quit();//退出事件循环}, Qt::DirectConnection);//timerconnect(m_timer_send_text, &QTimer::timeout, this, [=]{QByteArray data_buffer;data_buffer.append("xxx");SendBuffer(data_buffer, 0, m_tcpSocket);//发送数据,type:1视频、0文本}, Qt::DirectConnection);m_timer_send_text->start(SEND_INV);exec();//事件循环m_timer_send_text->stop();m_timer_send_text->deleteLater();m_tcpSocket->deleteLater();}private://发送数据,type:1视频、0文本void SendBuffer(const QByteArray &buffer, uint type, QTcpSocket *tcpSocket) const{QByteArray data = head_buffer;uint data_size = buffer.size();data.append(data_size).append(data_size>>8).append(data_size>>16).append(data_size>>24);data.append(type).append(type>>8).append(type>>16).append(type>>24);data.append(buffer);tcpSocket->write(data);}qintptr m_handle;//描述符QTcpSocket *m_tcpSocket;uint m_head;QByteArray head_buffer;QTimer *m_timer_send_text;
};#endif // TCPSOCKETTASK_H

回到gui线程,包含#include "mytcpsever.h"

构造

//tcpm_tcpSever = new MyTcpSever;bool ok = m_tcpSever->listen(QHostAddress::AnyIPv4, m_port);//建立监听if(!ok){QMessageBox::warning(nullptr, "致命错误", QString::number(m_port) + "端口被占用");QApplication::quit();//退出}qDebug() << "服务器开启\n监听端口: " << m_port;

析构

//tcpm_tcpSever->close();m_tcpSever->ClearTcpTask();delete m_tcpSever;

12.tcp客户端

头文件至少#include <QTcpSocket>

初始化

 //initm_online = false;m_head = TCP_BUFFER_HEAD;m_head_buffer.append(m_head>>24).append(m_head>>16).append(m_head>>8).append(m_head);
//tcpm_tcp_socket = new QTcpSocket;connect(m_tcp_socket, &QTcpSocket::connected, [=](){m_online = true;qDebug() << LOCAL_TIME + "连接成功!";});connect(m_tcp_socket, &QTcpSocket::readyRead, this, [=](){QByteArray recv_data = m_tcp_socket->readAll();if(recv_data.isNull()) return;});connect(m_tcp_socket, &QTcpSocket::disconnected, this, [=](){m_online = false;m_temp_buffer.clear();m_tcp_socket->close();qDebug() << LOCAL_TIME + "连接断开!";});

连接与断连,用按键写

void MainWindow::on_ConnectButton_clicked()//连接按键
{if(m_online){qDebug() << LOCAL_TIME + "忽略本次点击!";return;}m_serverIp = ui->ipEdit->text();m_serverPort = ui->portEdit->text().toUInt();m_tcp_socket->abort();m_tcp_socket->connectToHost(m_serverIp, m_serverPort);qDebug() << LOCAL_TIME + "尝试连接到" + m_serverIp + ":" + QString::number(m_serverPort);
}
void MainWindow::on_DisonnectButton_clicked()//断开按键
{if(!m_online){qDebug() << LOCAL_TIME + "忽略本次点击!";return;}m_tcp_socket->close();
}

13.开机自启

#define HEKY_AUTORUN "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
void mainWidget::AutoRun(bool flag)//设置开机自启,flag表示是否开机自启
{QString appName = QApplication::applicationName();QString appPath = QApplication::applicationFilePath();appPath = appPath.replace("/", "\\");//打开注册表QSettings *reg = new QSettings(HEKY_AUTORUN,//宏定义,自启动的注册表位置QSettings::NativeFormat);QString val = reg->value(appName).toString();//根据appName获取键值if (flag) {//打开开机自启if (val != appPath) {//键值不是本程序地址或者不存在,则写入键值reg->setValue(appName, appPath);}QString v = reg->value(appName).toString();//读取刚刚写入的键值if (v != appPath) {//写入失败ui->AutoStartcheckBox->setChecked(false);QMessageBox::warning(this, "拒绝访问", "添加注册表失败.", QMessageBox::Ok, QMessageBox::Ok);}} else {//关闭开机自启reg->remove(appName);//移除键值QString v = reg->value(appName).toString();if (v != "") {//键值仍然存在,移除失败ui->AutoStartcheckBox->setChecked(true);QMessageBox::warning(this, "拒绝访问", "移除注册表失败.", QMessageBox::Ok, QMessageBox::Ok);}}reg->deleteLater();//延迟删除
}bool mainWidget::isAutoRun()//判断是否打开开机自启
{QString appName = QApplication::applicationName();QString appPath = QApplication::applicationFilePath();appPath = appPath.replace("/", "\\");QSettings *reg = new QSettings(HEKY_AUTORUN,//宏定义,在头文件support.h里面QSettings::Registry64Format);//如果注册表键值就是本程序的地址,表示打开了开机自启QString val = reg->value(appName).toString();return val == appPath;
}

14.获取桌面背景窗口

HWND mainWidget::GetBackground()//获取背景窗体句柄
{//背景窗体没有窗体名,但是知道它的类名是workerW,且有父窗体Program Maneger,所以只要//遍历所有workW类型的窗体,逐一比较它的父窗体是不是Program Manager就可以找到背景窗体HWND hwnd = FindWindowA("progman", "Program Manager");HWND worker = NULL;do{worker = FindWindowExA(NULL, worker, "workerW", NULL);if (worker != NULL){char buff[200] = {0};int ret = GetClassNameA(worker, (PCHAR) buff, sizeof(buff) * 2);if (ret == 0)return NULL;}if (GetParent(worker) == hwnd){return worker;//返回结果}}while (worker != NULL);//没有找到//发送消息生成一个WorkerW窗体SendMessage(hwnd,0x052C,0,0);//重复上面步骤do{worker = FindWindowExA(NULL, worker, "workerW", NULL);if (worker != NULL){char buff[200] = {0};int ret = GetClassNameA(worker, (PCHAR) buff, sizeof(buff) * 2);if (ret == 0)return NULL;}if (GetParent(worker) == hwnd){return worker;//返回结果}}while (worker != NULL);return NULL;
}

要在qt下改壁纸可以这样

_BKWidget = new BKWidget;//壁纸显示widget
HWND hwnd = (HWND)_BKWidget->winId();//获取背景窗体的句柄
if(!SetBackground(hwnd))//把视频窗体设置成背景窗体的子窗体QMessageBox::information(this, "错误", "无法获取背景窗体的句柄");

其中

bool mainWidget::SetBackground(HWND child)//将child窗体设置成背景窗体的子窗体
{HWND background = GetBackground();if(background != 0){SetParent(child, GetBackground());return true;}return false;
}

15.64位32位自动切换库文件

contains(QT_ARCH, i386){
win32: LIBS += -L$$PWD/lib32/ -lquc
}else{
win32: LIBS += -L$$PWD/lib64/ -lquc
}

同理区分arm

unix{
contains(QT_ARCH, arm){}
else
{}
}

Qt常用却容易忘的功能记录相关推荐

  1. Qt常用控件介绍(一)

    Qt常用控件介绍 Qt Creator 的使用技巧 Qt Creator的常用快捷键 按钮 QPushButton QToolButton QRadioButton QCheckBox QComman ...

  2. qt 历史记录控件_基于Qt图形界面软件的操作日志记录方法及系统_2015106293015_说明书_专利查询_专利网_钻瓜专利网...

    技术领域 本发明涉及一种软件系统的日志记录技术,特别涉及一种基于Qt图形界面软件的操作日志记录方法及系统. 背景技术 软件操作日志是记录用户在使用软件的过程中,通过鼠标和键盘在操作界面上执行的点击和输 ...

  3. java前后端分离的实现方式_采用前后端分离的方式进行开发,实现了几种常用的文件上传功能...

    MyUploader-Backend 单文件上传,多文件上传,大文件上传,断点续传,文件秒传,图片上传 简介 采用前后端分离的方式进行开发,实现了几种常用的文件上传功能. 前端采用 vue.js + ...

  4. LeetCode中常用语言的一些基本方法记录

    文章目录 LeetCode中常用语言的一些基本方法记录 Java 数组 数组的常用操作及方法 Arrays工具类 Collections类常用方法总结 二维数组 字符串常用属性及方法 JavaScri ...

  5. 0004:Qt常用类 - QTime

    Qt常用类 - QTime 1 开发环境 在介绍内容之前,先说明一下开发环境,如下图: Qt版本:Qt5.3.2: Qt开发工具:Qt Creater 3.2.1: Qt构建工具:Desktop Qt ...

  6. 百科不全书之QT常用函数

    参考链接: 璎珞qc:Qt之QImage类. 沙振宇:Qt输出打印信息的日志到文件(两种方式). tandesir:Qt测算程序运行时间. 半生瓜のblog [QT]QT容器 百科不全书之QT常用函数 ...

  7. C++ | Qt 常用头文件及容器类

    目录 一.Qt常用头文件 1. <QtGlobal>头文件 (1) Qt 中的数据类型定义 (2) 常用函数 (3) 常用宏 2.<QMath>头文件 二.Qt容器类 1.顺序 ...

  8. Qt学习之路(1)------Qt常用类用法说明

    Qt常用类 向控制台输出文本 第一个例子,我们采用STL的方式: console.cpp #include <iostream>int main() {std::cout << ...

  9. QT使用SQLite数据库实现登录功能

    QT实现用户登录功能(MySQL) https://blog.csdn.net/tianya_team/article/details/72566198 QT5中使用SQLite https://bl ...

最新文章

  1. python是干什么用的视频-python基础教程千锋最新视频学完之后可以做什么
  2. Java 8 Stream API详解--转
  3. Google发布Android Studio 1.0
  4. LeetCode14 最长公共前缀
  5. Vue项目启动webpack报错Module build failed: Error: No PostCSS Config found in......
  6. 我的MarkDown入门
  7. 【POJ - 2392】Space Elevator (dp,优秀的背包问题)
  8. python获取网页元素坐标_Python实战爬虫系统学习笔记一:解析网页中的元素
  9. 随想录(怎么用source insight阅读kernel代码)
  10. linux学习笔记:如何更改文件属性?
  11. 梯度下降来龙去脉附matlab代码
  12. MLOps- 吴恩达Andrew Ng Overview of the ML Lifecycle and Deployment Week1 部署深度学习模型model 实现作业
  13. easyui 全部图标
  14. 代码题--C++--小米--英文句子字符串反转
  15. 洛谷 P3373 线段树模板题
  16. 《自然-机器智能》:神经形态技术可使大型深度学习网络节能16倍
  17. Cisco 新兴网络技术考试答案
  18. python splitext()函数
  19. 企业工程行业管理系统源码-专业的工程管理软件-提供一站式服务
  20. 制作u盘启动linux安装教程,制作u盘启动linux安装教程

热门文章

  1. 云平台编程与开发(一):云平台服务商一览
  2. 淘宝网自主开发数据存储系统
  3. wuc-tab标签点击不了_不干胶标签专属定制
  4. 安迪·鲁宾支持的猫头鹰实验室刚推出了一款机器人视频会议摄像机
  5. Jetson-Xavier-NX刷机+pytorch环境配置+yolov5运行
  6. mysql如何加索引的时候不锁表
  7. JavaScript中的对象,如何创建对象,创建对象的7种模式
  8. C++语言学习(八)——操作符重载
  9. nodeJs处理json
  10. [Wi-Fi抓包篇]3. WireShark ——抓wlan口包的方法