Qt自定义标题栏
效果如下:

代码如下:
// widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();
protected:bool nativeEvent(const QByteArray&eventType,void *message,long*result) override;
private slots:void on_close();private:void mousePressEvent(QMouseEvent*ev);void mouseMoveEvent(QMouseEvent*ev);QPoint pos;
private:Ui::Widget *ui;int m_BorderWidth =5;
};//2、titlebar
#ifndef CTABTITLEWIDGET_H
#define CTABTITLEWIDGET_H#include <QObject>
#include <QWidget>
#include<QPushButton>class CTabTitleWidget : public QWidget
{Q_OBJECT
public:explicit CTabTitleWidget(QWidget *parent = nullptr);~CTabTitleWidget();void setEmptyWidgetWidth(int w);protected:void paintEvent(QPaintEvent*event);void mousePressEvent(QMouseEvent*ev);void mouseDoubleClickEvent(QMouseEvent*event);signals:void sig_close();void sig_addtab();
private slots:void on_clicked();private:QPushButton* m_pAddBtn = nullptr;QWidget* m_pEmptyWidget = nullptr;QPushButton* m_pUserBtn = nullptr;QPushButton* m_pMinBtn = nullptr;QPushButton* m_pMaxBtn = nullptr;QPushButton* m_pCloseBtn = nullptr;
};#endif // CTABTITLEWIDGET_H#endif // WIDGET_H//3.tabbrowser
#ifndef TABBROWSER_H
#define TABBROWSER_H#include <QObject>
#include <QWidget>
#include <QTabWidget>
#include <QMenu>
#include "ctabtitlewidget.h"
class tabbrowser : public QTabWidget
{Q_OBJECT
public:explicit tabbrowser(QWidget *parent = nullptr);enum TAB_FLAG{NEW,CLOSE,NORMAL,SPECIAL};protected:void resizeEvent(QResizeEvent*ev) override;private:void initTabWidget();void setTabBarFlag(TAB_FLAG);void createTabMenu();private slots:void on_newTab();void on_closeTab(int index);void onMenuShow(const QPoint&pos);void on_closeAllTab();private:CTabTitleWidget*m_pRightWidget = nullptr;QMenu* m_pTabMenu = nullptr;
signals:void sig_close();};#endif // TABBROWSER_H
.cpp
/./1.widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "tabbrowser.h"
#ifdef Q_OS_WIN
#include <qt_windows.h>
#include <Windows.h>
#include <windowsx.h>
#include <QHBoxLayout>
#include <QMouseEvent>
#endifWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 设置窗口为无边框setWindowFlag(Qt::FramelessWindowHint);setStyleSheet("background-color:#E3E4E7;");// 创建一个新的 tabbrowser 实例,并将其设置为此窗口的小部件tabbrowser* pTab = new tabbrowser(this);// 创建一个水平布局,并将 tabbrowser 添加到布局中QHBoxLayout* pHLay = new QHBoxLayout(this);pHLay->addWidget(pTab);pHLay->setContentsMargins(6, 6, 6, 6);setLayout(pHLay);// 连接 tabbrowser 的关闭信号到此窗口的 on_close 槽函数connect(pTab, &tabbrowser::sig_close, this, &Widget::on_close);
}Widget::~Widget()
{delete ui;
}// 处理自定义窗口行为的原生事件(例如,调整大小和移动)
bool Widget::nativeEvent(const QByteArray &eventType, void *message, long *result)
{Q_UNUSED(eventType)MSG* param = static_cast<MSG*>(message);switch (param->message){case WM_NCHITTEST:{int nX = GET_X_LPARAM(param->lParam) - this->geometry().x();int nY = GET_Y_LPARAM(param->lParam) - this->geometry().y();// 如果鼠标位于子控件上,则忽略此事件if (childAt(nX, nY) != nullptr)return QWidget::nativeEvent(eventType, message, result);// 当鼠标靠近边框时,进行调整大小操作if ((nX > 0) && (nX < m_BorderWidth))*result = HTLEFT;if ((nX > this->width() - m_BorderWidth) && (nX < this->width()))*result = HTRIGHT;if ((nY > 0) && (nY < m_BorderWidth))*result = HTTOP;if ((nY > this->height() - m_BorderWidth) && (nY < this->height()))*result = HTBOTTOM;if ((nX > 0) && (nX < m_BorderWidth) && (nY > 0) && (nY < m_BorderWidth))*result = HTTOPLEFT;if ((nX > this->width() - m_BorderWidth) && (nX < this->width()) && (nY > 0) && (nY < m_BorderWidth))*result = HTTOPRIGHT;if ((nX > 0) && (nX < m_BorderWidth) && (nY > this->height() - m_BorderWidth) && (nY < this->height()))*result = HTBOTTOMLEFT;if ((nX > this->width() - m_BorderWidth) && (nX < this->width()) && (nY > this->height() - m_BorderWidth) && (nY < this->height()))*result = HTBOTTOMRIGHT;return true;}}return QWidget::nativeEvent(eventType, message, result);
}// 处理关闭信号的槽函数
void Widget::on_close()
{close();
}// 处理鼠标按下事件以移动窗口
void Widget::mousePressEvent(QMouseEvent *ev)
{if (Qt::LeftButton == ev->button()){// 计算鼠标相对于窗口左上角的位置pos = ev->globalPos() - frameGeometry().topLeft();ev->accept();}
}// 处理鼠标移动事件以移动窗口
void Widget::mouseMoveEvent(QMouseEvent *ev)
{if (Qt::LeftButton & ev->buttons()){// 移动窗口到鼠标移动后的位置move(ev->globalPos() - pos);ev->accept();}
}
//2.titlebar
#include “CTabTitleWidget.h”
#include
#include
#include
#include
#ifdef Q_OS_WIN
#include <qt_windows.h>
#pragma comment(lib, “user32.lib”)
#endif
CTabTitleWidget::CTabTitleWidget(QWidget *parent)
: QWidget{parent}
{
setStyleSheet(“background-color:#E3E4E7”);
m_pAddBtn = new QPushButton(this);
m_pAddBtn->setFlat(true);
m_pAddBtn->setFixedSize(32, 32);
m_pAddBtn->setStyleSheet(“background-image:url(:/resources/add.svg)”);
m_pEmptyWidget = new QWidget(this);m_pUserBtn = new QPushButton(this);
m_pUserBtn->setFlat(true);
m_pUserBtn->setFixedSize(32, 32);
m_pUserBtn->setStyleSheet("background-image:url(:/resources/user)");m_pMinBtn = new QPushButton(this);
m_pMinBtn->setFlat(true);
m_pMinBtn->setFixedSize(32, 32);
m_pMinBtn->setStyleSheet("background-image:url(:/resources/min.svg)");m_pMaxBtn = new QPushButton(this);
m_pMaxBtn->setFlat(true);
m_pMaxBtn->setFixedSize(32, 32);
m_pMaxBtn->setStyleSheet("background-image:url(:/resources/max.svg)");m_pCloseBtn = new QPushButton(this);
m_pCloseBtn->setFlat(true);
m_pCloseBtn->setFixedSize(32, 32);
m_pCloseBtn->setStyleSheet("background-image:url(:/resources/close.svg)");QHBoxLayout* pHLay = new QHBoxLayout(this);
pHLay->addWidget(m_pAddBtn);
pHLay->addWidget(m_pEmptyWidget);
this->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
pHLay->addWidget(m_pUserBtn);
pHLay->addSpacing(8);
pHLay->addWidget(m_pMinBtn);
pHLay->addWidget(m_pMaxBtn);
pHLay->addWidget(m_pCloseBtn);
pHLay->setContentsMargins(1, 0, 1, 3);
setLayout(pHLay);connect(m_pAddBtn, &QPushButton::clicked, this, &CTabTitleWidget::on_clicked);
connect(m_pMinBtn, &QPushButton::clicked, this, &CTabTitleWidget::on_clicked);
connect(m_pMaxBtn, &QPushButton::clicked, this, &CTabTitleWidget::on_clicked);
connect(m_pCloseBtn, &QPushButton::clicked, this, &CTabTitleWidget::on_clicked);
}
CTabTitleWidget::~CTabTitleWidget()
{
}
void CTabTitleWidget::setEmptyWidgetWidth(int w)
{
m_pEmptyWidget->setMinimumWidth(w);
}
void CTabTitleWidget::paintEvent(QPaintEvent *event)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
QWidget::paintEvent(event);
}
void CTabTitleWidget::mousePressEvent(QMouseEvent ev)
{
if(ReleaseCapture())
{
QWidgetwin = this->window();
if(win->isTopLevel())
{
SendMessage(HWND(win->winId()),WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);
}
}
ev->ignore();
}
void CTabTitleWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
emit m_pMaxBtn->clicked();
}
void CTabTitleWidget::on_clicked()
{
QPushButtonbtn = qobject_cast<QPushButton>(sender());
QWidget*win = this->window();
if(win->isTopLevel())
{
if (btn == m_pAddBtn)
{
emit sig_addtab();
}
else if (btn == m_pMinBtn)
{
win->showMinimized();
}
else if (btn == m_pMaxBtn)
{
win->isMaximized() ? win->showNormal() : win->showMaximized();
}
else if (btn == m_pCloseBtn)
{
emit sig_close();
}
}
}
//3.tabbrowser
#include “tabbrowser.h”
#include
#include
#include
#include
#include
QString qss0 = “QTabBar::tab{
font: 75 12pt Arial;
text-align:left;
width:184px;
height:32;
background:#FFFFFF;
border:2px solid #FFFFFF;
border-bottom-color:#FFFFFF;
border-top-left-radius:4px;
border-top-right-radius:4px;
padding:2px;
margin-top:0px;
margin-right:1px;
margin-left:1px;
margin-bottom:0px;}
QTabBar::tab:selected{
color:#333333; /文字颜色/
background-color:#FFFFFF;}
QTabBar::tab:!selected{
color:#B2B2B2;
border-color:#FFFFFF;}
QTabBar::scroller{width: 0px;}”;
QString qss1 = "QTabBar::tab{ \
font: 75 12pt Arial; \
text-align:left; \
width:184px; \
height:32; \
background:#FFFFFF; \
border:2px solid #FFFFFF; \
border-bottom-color:#FFFFFF; \
border-top-left-radius:4px; \
border-top-right-radius:4px; \
padding:2px; \
margin-top:0px; \
margin-right:1px; \
margin-left:1px; \
margin-bottom:0px;} \
QTabBar::tab:selected{ \color:#333333; /*文字颜色*/ \background-color:#FFFFFF;} \
QTabBar::tab:!selected{ \color:#B2B2B2; \border-color:#FFFFFF;} \
QTabBar::scroller{width: 36px;}";
- tabbrowser::tabbrowser(QWidget *parent)
- QTabWidget{parent}
{
this->addTab(new QWidget,u8"稻壳");
this->setUsesScrollButtons(true);//滚动鼠标可切换tab
this->setTabsClosable(true); //显示tab右侧的关闭按钮
this->setMovable(true);//设置可移动位置
initTabWidget();
setTabBarFlag(NORMAL);this->setStyleSheet(qss0);connect(this, &QTabWidget::tabCloseRequested,this, &tabbrowser::on_closeTab);
}
void tabbrowser::resizeEvent(QResizeEvent *ev)
{
setTabBarFlag(NORMAL);
QTabWidget::resizeEvent(ev);
}
void tabbrowser::initTabWidget()
{
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this,&QTabWidget::customContextMenuRequested,this,&tabbrowser::onMenuShow);
createTabMenu();
m_pRightWidget = new CTabTitleWidget(this);this->setCornerWidget(m_pRightWidget, Qt::TopRightCorner);
connect(m_pRightWidget, &CTabTitleWidget::sig_addtab, this, &tabbrowser::on_newTab);
connect(m_pRightWidget, &CTabTitleWidget::sig_close, this, &tabbrowser::sig_close);
}
void tabbrowser::setTabBarFlag(TAB_FLAG flag)
{
int w = this->width();
int tabsWidth = 0; //所有tab的总宽度
int tabsHeight = tabBar()->height();
int tabs = this->count();if (flag == NEW || flag == NORMAL)
{for (int i = 0; i < tabs; ++i){tabsWidth += tabBar()->tabRect(i).width();}
}
else
{for (int i = 0;i < tabs - 1;++i){tabsWidth += tabBar()->tabRect(i).width();}
}if (w > tabsWidth)
{m_pRightWidget->setEmptyWidgetWidth(w - tabsWidth - 32 * 5 - 15);this->setStyleSheet(qss0);
}
else
{//当所有tab的宽度大于整个tabWidget的宽时m_pRightWidget->setEmptyWidgetWidth(150);this->setStyleSheet(qss1);
}
}
void tabbrowser::createTabMenu()
{
m_pTabMenu = new QMenu(this);
QAction* pAcSave = new QAction(QIcon(":/resources/save.png"), u8"保存", m_pTabMenu);
m_pTabMenu->addAction(pAcSave);connect(pAcSave, &QAction::triggered, [=] {QMessageBox::information(this, u8"提示", u8"你点击了 保存");});QAction* pAcSaveAs = new QAction(QString(u8"另存为"), m_pTabMenu);
m_pTabMenu->addAction(pAcSaveAs);m_pTabMenu->addSeparator();QAction* pAcShareDoc = new QAction(QIcon(":/resources/share.png"), QString(u8"分享文档"), m_pTabMenu);
m_pTabMenu->addAction(pAcShareDoc);QAction* pAcSendToDevice = new QAction(QString(u8"发送到设备"), m_pTabMenu);
m_pTabMenu->addAction(pAcSendToDevice);m_pTabMenu->addSeparator();QAction* pAcNewName = new QAction(QString(u8"重命名"), m_pTabMenu);
m_pTabMenu->addAction(pAcNewName);QAction* pAcSaveToWPSCloud = new QAction(QString(u8"保存到WPS云文档"), m_pTabMenu);
m_pTabMenu->addAction(pAcSaveToWPSCloud);QAction* pAcCloseAll = new QAction(QString(u8"关闭所有文件"), m_pTabMenu);
m_pTabMenu->addAction(pAcCloseAll);
connect(pAcCloseAll, &QAction::triggered, this, &tabbrowser::on_closeAllTab);
}
void tabbrowser::on_newTab()
{
int nCount = count();
QString title = QString::number(nCount);
title = “Page” + title;
// 这里写的有问题,应该是 insertTab
this->addTab(new QWidget, title);if (!tabsClosable())
{setTabsClosable(true);
}setTabBarFlag(NEW);
}
void tabbrowser::on_closeTab(int index)
{
widget(index)->deleteLater();
setTabBarFlag(CLOSE);
//当只剩下1个tab时
if (count() == 1)
{setTabsClosable(false);setTabBarFlag(SPECIAL);
}
}
void tabbrowser::onMenuShow(const QPoint &pos)
{
int index = this->tabBar()->tabAt(pos);
#ifdef _DEBUG
qDebug() << u8"当前tab为:" << QString::number(index);
this->setCurrentIndex(index);
#endif
if (index != -1)
{m_pTabMenu->exec(QCursor::pos());
}
}
void tabbrowser::on_closeAllTab()
{
}
相关文章:
Qt自定义标题栏
效果如下: 代码如下: // widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr…...
java如何向数组中插入元素
java的数组是不可改变的,因此如果要向数组中插入新的元素,需要新建一个数组,新的数组元素个数减去老数组元素个数的差大于等于要插入新的元素数量。 假如说要插入一个数组元素,需要把新元素插入到中间,把新的数组分为…...
4、PHP的xml注入漏洞(xxe)
青少年ctf:PHP的XXE 1、打开网页是一个PHP版本页面 2、CTRLf搜索xml,发现2.8.0版本,含有xml漏洞 3、bp抓包 4、使用代码出发bug GET /simplexml_load_string.php HTTP/1.1 补充: <?xml version"1.0" encoding&quo…...
设计模式-解释器模式
作者持续关注 WPS二次开发专题系列,持续为大家带来更多有价值的WPS开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(QQ:250325397) 定义 解释器模式(Interpreter Pattern&…...
NDIS驱动程序堆栈
NDIS 6.0 引入了暂停和重启驱动程序堆栈的功能。 若要支持 NDIS 6.0 提供的堆栈管理功能,必须重写旧版驱动程序。 NDIS 6.0 还引入了 NDIS Filter驱动程序。 Filter驱动程序可以监视和修改协议驱动程序与微型端口驱动程序之间的交互。 与 NDIS 5 相比,F…...
大数据开发面试题【数仓篇】
197、数据仓库和传统数据库区别 由于历史数据使用频率过低,导致数据堆积,查询性能下降;用于查询分析,涉及大量的历史数据,数据仓库中的数据一般来日志文件和事务 数据库是跟业务挂钩的,数据库不可能装下一…...
Leetcode刷题笔记5
76. 最小覆盖子串 76. 最小覆盖子串 - 力扣(LeetCode) 解法一: 暴力枚举 哈希表 先定义left和right,可以在随机位置 枚举一个位置向后找,找到一个位置之后,发现这段区间是一个最小的区间之后,…...
【Qt】Qt中的信号槽
一、信号和槽概述 信号槽是Qt矿建引以为豪的机制之一。 所谓信号槽,实际上就是观察者模式(发布——订阅模式)。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号。这种发出的信号是…...
VsCode个人插件
Auto Rename Tag > 同时修改标签 Rainbow Brackets > 不同层级不同括号颜色 Dracula Official > 个人比较喜欢的一款主题 Error Lens > 错误信息显示 ES7REACT/Redux/React-Native>react开发插件 ESLINT Indenticator>方便看结构 Prettier Formatter …...
Docker环境安装并使用Elasticsearch
1、拉取es docker pull elasticsearch:7.10.12、查看镜像 docker images3、启动es docker run -d --name esearch -p 9200:9200 -p 9300:9300 elasticsearch:7.10.14、如果启动ES时出现一下问题 Unable to find image docker.elastic.co/elasticsearch/elasticsearch:7.10.…...
中心渗透Ⅱ
cs与msf权限传递以及mimikatz抓取win2012明文密码 使用Cobalt Strike抓取win2012明文密码,将会话传递到Metasploit Framework上 1.cs生成木马并使目标服务器中马 建立监听生成木马 2.抓取目标主机的明文密码 通过修改注册表来让Wdigest Auth保存明文口令 shell …...
【webrtc】RtpToNtpEstimator:最小二乘法、ntp估计及c++实例
上一篇: 【webrtc】RtpToNtpEstimator:将 RTP 时间戳映射到 NTP 时间 分析了最小二乘法的实现及对rtp到ntp的映射计算的调用流程 基于最小二乘法进行估计 RtpToNtpEstimator::Estimate G:\CDN\rtcCli\m98\src\system_wrappers\source\rtp_to_ntp_estimator.cc RtpToNtpEstima…...
【DevOps】Elasticsearch在Ubuntu 20.04上的安装与配置:详细指南
目录 一、ES 简介 1、核心概念 2、工作原理 3、 优势 二、ES 在 Ubuntu 20.04 上的安装 1、安装 Java 2、下载 ES 安装包 3、创建 ES 用户 4 、解压安装包 5、 配置 ES 6、 启动 ES 7、验证安装 三、ES 常用命令 1、创建索引 2、 插入文档 3、查询文档 四、ES…...
windows内存管理
一 windows系统的内存管理涉及哪些 1.1 虚拟内存管理机制 windows操作系统使用虚拟内存技术,将磁盘文件,通过映射对象(存储在物理内存)关联,映射到虚拟内存作为文件试图。即用户操作"虚拟内存中File View Objec…...
c++ 将指针转换为 void* 后,转换为怎么判断原指针类型?
当将指针转换为void后,擦除了指针所指向对象的类型信息,因此无法通过void指针来判断原始指针的类型。我这里有一套编程入门教程,不仅包含了详细的视频讲解,项目实战。如果你渴望学习编程,不妨点个关注,给个…...
Swift 属性
属性 一、存储属性1、常量结构体实例的存储属性2、延时加载存储属性3、存储属性和实例变量 二、计算属性1、简化 Setter 声明2、简化 Getter 声明3、只读计算属性 三、属性观察器四、属性包装器1、设置被包装属性的初始值2、从属性包装器中呈现一个值 五、全局变量和局部变量六…...
基于maxkey接入jeecgboot并实现账户同步
1. 注册应用 1.1 在统一认证中心注册第三方应用 1.1.1 填写应用名和登录地址 1.1.2 填写认证地址授权方式和作用域 1.1.3 选择权限范围并提交 1.2 配置访问权限 1.2.1 指定用户组 1.1.2 选择注册的应用 1.1.3 在单点登录认证页面查看添加的应用 1.3 同步一个第三方应用的账号…...
kafka Kerberos集群环境部署验证
背景 公司需要对kafka环境进行安全验证,目前考虑到的方案有Kerberos和SSL和SASL_SSL,最终考虑到安全和功能的丰富度,我们最终选择了SASL_SSL方案。处于知识积累的角度,记录一下kafka keberos安装部署的步骤。 机器规划 目前测试环境公搭建了三台kafka主机服务,现在将详细…...
[C++]debug介绍+debug时如何查看指针指向内存处的值
一、简介 预备工具和知识:使用使用VSCode使用Debug。 本文简介:本文将简要介绍debug中Continue,Step Over,Step Into和Restart的功能。并介绍如何在debug时查看动态内存地址(指针)的值; 二、D…...
AI学习指南数学工具篇-凸优化在支持逻辑回归中的应用
AI学习指南数学工具篇-凸优化在支持逻辑回归中的应用 一、引言 在人工智能领域,逻辑回归是一种常见的分类算法,它通过学习样本数据的特征和标签之间的关系,来进行分类预测。而在逻辑回归算法中,凸优化是一种重要的数学工具&…...
三自由度机械臂DH参数建模常见误区盘点:你的Xi-1轴方向真的设对了吗?
三自由度机械臂DH参数建模常见误区盘点:你的Xi-1轴方向真的设对了吗? 在机械臂运动学建模领域,DH(Denavit-Hartenberg)参数法堪称经典,但看似简洁的四个参数背后藏着无数"坑"。尤其当面对三自由度…...
程序员35岁以后最好的投资:不是买房,是这3样东西
当“35岁红线”撞上测试人的职业围城如果你在某个深夜刷到“程序员35岁以后该何去何从”的帖子时,心底划过一丝隐痛,那你绝不是一个人。而对于软件测试从业者而言,这种焦虑往往被放大得更加具体——当“点点点”的手工测试逐渐被自动化替代&a…...
如何5分钟搞定HTML转Word难题:html-to-docx终极实战指南
如何5分钟搞定HTML转Word难题:html-to-docx终极实战指南 【免费下载链接】html-to-docx HTML to DOCX converter 项目地址: https://gitcode.com/gh_mirrors/ht/html-to-docx 还在为复制粘贴HTML到Word时格式乱码而头疼吗?每次都要手动调整表格边…...
终极指南:如何使用NifSkope轻松编辑游戏3D模型文件
终极指南:如何使用NifSkope轻松编辑游戏3D模型文件 【免费下载链接】nifskope A git repository for nifskope. 项目地址: https://gitcode.com/gh_mirrors/ni/nifskope NifSkope是一款专为游戏开发者设计的开源3D模型编辑器,专注于NetImmerse文件…...
CSerialPort 4.3.2 保姆级集成指南:5分钟让你的QT/MFC/Electron项目拥有稳定串口功能
CSerialPort 4.3.2 全栈集成实战:从QT到Electron的跨平台串口方案 在工业控制、物联网设备调试和嵌入式系统开发中,串口通信作为最基础也最可靠的数据传输方式之一,至今仍发挥着不可替代的作用。然而,不同操作系统提供的串口API差…...
Sunshine游戏串流服务器:5步搭建你的终极私人云游戏平台
Sunshine游戏串流服务器:5步搭建你的终极私人云游戏平台 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 想要在任何设备上畅玩PC游戏,却受限于硬件性能&…...
Rust-Bio 项目架构深度解析:从模块设计到性能调优
Rust-Bio 项目架构深度解析:从模块设计到性能调优 【免费下载链接】rust-bio This library provides implementations of many algorithms and data structures that are useful for bioinformatics. All provided implementations are rigorously tested via conti…...
三步破解安全研发合规难题:Gitee软件工厂助力GJB5000B与等保三级高标准落地
TL;DR 国家安全领域软件研发需同时满足GJB5000B、等保2.0三级等强制合规要求与智能化装备带来的软件复杂度挑战。传统研发模式在协作、安全、交付三方面日益乏力。Gitee软件工厂通过“统一底座、细粒度权限、标准化流程”三大核心能力,内置SM2/SM4国密加密、IP白名单…...
FreeMove:Windows系统C盘空间终极清理方案,无需重装释放数十GB
FreeMove:Windows系统C盘空间终极清理方案,无需重装释放数十GB 【免费下载链接】FreeMove Move directories without breaking shortcuts or installations 项目地址: https://gitcode.com/gh_mirrors/fr/FreeMove 还在为C盘空间不足而烦恼吗&…...
5分钟搞定百度网盘限速:baidu-wangpan-parse全功能指南
5分钟搞定百度网盘限速:baidu-wangpan-parse全功能指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 还在为百度网盘的限速而烦恼吗?想下载大文件却只…...
